
/*
    Software License

    Copyright (C) 2021-05-24  Xoronos

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, version 3.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

/*
    Liabilities

    The software is provided "AS IS" without any warranty of any kind, either expressed,
    implied, or statutory, including, but not limited to, any warranty that the software
    will conform to specifications, any implied warranties of merchantability, fitness
    for a particular purpose, and freedom from infringement, and any warranty that the
    documentation will conform to the software, or any warranty that the software will
    be error free.

    In no event shall Xoronos be liable for any damages, including, but not limited to,
    direct, indirect, special or consequential damages, arising out of, resulting from,
    or in any way connected with this software, whether or not based upon warranty,
    contract, tort, or otherwise, whether or not injury was sustained by persons or
    property or otherwise, and whether or not loss was sustained from, or arose out of
    the results of, or use of, the software or services provided hereunder.

    To request the provided software under a different license you can contact us at
    support@xoronos.com
*/

#include "xrn_crypto.h"
#include <pthread.h>

int xrn_permute_ring_signature_wrapper( FILE * signer_binomial_key_fpr,
                                        FILE * verifier_binomial_key_fpr,
                                        FILE * signer_ring_signature_fpr,
                                        FILE * verifier_ring_signature_fpr,
                                        FILE * ring_signature_fpw, xrn_crypto_extra_settings_t settings
 )
{

    XPRINT_DEB(  );
    int ret, final_ret;
    xbinomial_key_t signer_binomial_key;
    xbinomial_key_t verifier_binomial_key;
    xring_signature_t signer_ring_signature;
    xring_signature_t verifier_ring_signature;
    xring_signature_t permute_ring_signature;

    final_ret = XSUCCESS;

    if ( ( verifier_binomial_key_fpr == NULL ) || ( signer_binomial_key_fpr == NULL )
         || ( verifier_ring_signature_fpr == NULL ) || ( signer_ring_signature_fpr == NULL )
         || ( ring_signature_fpw == NULL ) ) {
        XPRINT_ERR( 1203, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load binomial key
    ret = xrn_load_binomial_key( &signer_binomial_key, signer_binomial_key_fpr, &settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1210, XERR_GENERAL_MSG );
        return ret;
    }

    // load binomial key
    ret = xrn_load_binomial_key( &verifier_binomial_key, verifier_binomial_key_fpr, &settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1211, XERR_GENERAL_MSG );
        return ret;
    }

    // load ring signature key
    ret = xrn_load_ring_signature( &signer_ring_signature, signer_ring_signature_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1207, XERR_GENERAL_MSG );
        return ret;
    }

    // load ring signature key
    ret = xrn_load_ring_signature( &verifier_ring_signature, verifier_ring_signature_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1208, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_permute_ring_signature( signer_binomial_key, verifier_binomial_key, signer_ring_signature,
                                    verifier_ring_signature, &permute_ring_signature, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1209, XERR_GENERAL_MSG );
        return ret;
    }

    // dump ring signature

    ret = xrn_dump_ring_signature( permute_ring_signature, 1, ring_signature_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1206, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_permute_ring_signature( xbinomial_key_t signer_binomial_key,
                                xbinomial_key_t verifier_binomial_key,
                                xring_signature_t signer_ring_signature,
                                xring_signature_t verifier_ring_signature,
                                xring_signature_t * permuted_ring_signature,
                                xrn_crypto_extra_settings_t settings
 )
{
    int i, neq0, neq1, final_ret;
    int signer_binomial_key_found, signer_binomial_key_index;
    int verifier_binomial_key_found, verifier_binomial_key_index;
    xring_signature_t permuted_ring_signature_local;
    xnum_t tmp0, tmp1;

    XPRINT_DEB(  );
    final_ret = XSUCCESS;

    if ( permuted_ring_signature == NULL ) {
        XPRINT_ERR( 1204, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check start points

    tmp0 = signer_ring_signature.binomial_keys[0].start;
    tmp1 = verifier_ring_signature.binomial_keys[0].start;
    XNUM_CMP( tmp0, tmp1, neq0 );

    if ( neq0 == 1 ) {
        XPRINT_ERR( 1205, XERR_IO_MSG );
        return XERR_IO;
    }

    // copy from verifier
    permuted_ring_signature_local.ring_size = verifier_ring_signature.ring_size;
    verifier_binomial_key_found = 0;
    signer_binomial_key_found = 0;
    verifier_binomial_key_index = 0;
    signer_binomial_key_index = 0;

    for ( i = 0; i < verifier_ring_signature.ring_size; i++ ) {

        permuted_ring_signature_local.binomial_keys[i] = verifier_ring_signature.binomial_keys[i];

        // check for signer binomial key
        tmp0 = permuted_ring_signature_local.binomial_keys[i].start;
        XNUM_CMP( tmp0, signer_binomial_key.start, neq0 );
        tmp0 = permuted_ring_signature_local.binomial_keys[i].end;
        XNUM_CMP( tmp0, signer_binomial_key.end, neq1 );
        if ( ( neq0 == 0 ) && ( neq1 == 0 ) ) {
            signer_binomial_key_found = 1;
            signer_binomial_key_index = i;
        }

        // check for verifier binomial key
        tmp1 = permuted_ring_signature_local.binomial_keys[i].start;
        XNUM_CMP( tmp1, verifier_binomial_key.start, neq0 );
        tmp1 = permuted_ring_signature_local.binomial_keys[i].end;
        XNUM_CMP( tmp1, verifier_binomial_key.end, neq1 );
        if ( ( neq0 == 0 ) && ( neq1 == 0 ) ) {
            verifier_binomial_key_found = 1;
            verifier_binomial_key_index = i;
        }

    }

    if ( ( verifier_binomial_key_found == 0 ) && ( signer_binomial_key_found == 0 ) ) {
        permuted_ring_signature_local.binomial_keys[0] = signer_binomial_key;
        permuted_ring_signature_local.binomial_keys[1] = verifier_binomial_key;
    } else if ( ( verifier_binomial_key_found == 0 ) && ( signer_binomial_key_found == 1 ) ) {
        for ( i = 0; ( i < verifier_ring_signature.ring_size ) && ( verifier_binomial_key_found == 0 ); i++ ) {
            if ( i != signer_binomial_key_index ) {
                permuted_ring_signature_local.binomial_keys[i] = verifier_binomial_key;
                verifier_binomial_key_found = 1;
            }

        }

    } else if ( ( verifier_binomial_key_found == 1 ) && ( signer_binomial_key_found == 0 ) ) {
        for ( i = 0; ( i < verifier_ring_signature.ring_size ) && ( signer_binomial_key_found == 0 ); i++ ) {
            if ( i != verifier_binomial_key_index ) {
                permuted_ring_signature_local.binomial_keys[i] = signer_binomial_key;
                signer_binomial_key_found = 1;
            }

        }

    }

    // copy from signer
    permuted_ring_signature_local.hint = signer_ring_signature.hint;
    permuted_ring_signature_local.proof = signer_ring_signature.proof;

    if ( shuffle_binomial_keys( &permuted_ring_signature_local ) != 0 ) {
        XPRINT_ERR( 1202, XERR_NULL_MSG );
        return XERR_NULL;
    }

    *permuted_ring_signature = permuted_ring_signature_local;

    return final_ret;

}

int xrn_estimate_steg_block_length( FILE * envelop_fpi, uint8_t folding_en, uint64_t * capacity
 )
{

    XPRINT_DEB(  );

    uint64_t available_capacity;
    char tabs[5];

    if ( ( xlog.not_fp == NULL ) || ( envelop_fpi == NULL ) || ( capacity == NULL ) ) {
        XPRINT_ERR( 785, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( ( folding_en != 0 ) && ( folding_en != 1 ) ) {
        XPRINT_ERR( 1175, XERR_IO_MSG );
        return XERR_IO;
    }

    // Determine the file size
    if ( 0 != fseek( envelop_fpi, 0, SEEK_END ) ) {
        XPRINT_ERR( 784, XERR_IO_MSG );
        return XERR_IO;
    }

    available_capacity = ( uint64_t ) ftell( envelop_fpi );

    rewind( envelop_fpi );

    // if the capacity is too small
    if ( ( available_capacity / 4 ) < sizeof( header_block_t ) + sizeof( uint32_t ) ) {
        XPRINT_ERR( 804, XERR_IO_MSG );
        return XERR_IO;
    }

    //       actual capacity, block header,            crc32
    available_capacity = ( available_capacity / 4 ) - sizeof( header_block_t ) - sizeof( uint32_t );

    if ( available_capacity <= 256 ) {
        XPRINT_ERR( 1169, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( folding_en == 0 ) {
        available_capacity = available_capacity - 256;
    }

    strncpy( tabs, "   ", 4 );

    *capacity = available_capacity;

    if ( folding_en == 1 ) {
        if ( available_capacity <= 512 ) {
            if ( xlog.not_en ) {
                fprintf( xlog.not_fp,
                         "{\n%s\"message_type\" : \"steganography_block_length\",\n%s\"folding_en\" : 0,\n%s\"byte_capacity\" : %lu \n}\n",
                         tabs, tabs, tabs, available_capacity );
            }

            XPRINT_WAR( XWAR_STEG_CAPACITY_MSG, XWAR_STEG_CAPACITY );
            return ( int ) XWAR_STEG_CAPACITY;
        } else {
            if ( xlog.not_en ) {
                fprintf( xlog.not_fp,
                         "{\n%s\"message_type\" : \"steganography_block_length\",\n%s\"folding_en\" : 1,\n%s\"byte_capacity\" : %lu \n}\n",
                         tabs, tabs, tabs, available_capacity );
            }

        }

    }

    return XSUCCESS;

}

int xrn_make_steg_raw( FILE * encoded_fpi, FILE * envelop_fpi, FILE * envelop_fpo
 )
{
    XPRINT_DEB(  );

    uint8_t c;
    size_t bytes_read;
    size_t bytes_written;
    size_t bytes_to_write;
    uint32_t tmp32, out32;
    int i;
    int final_ret;
    uint8_t buffer[4096];

    final_ret = XSUCCESS;

    if ( ( encoded_fpi == NULL ) || ( envelop_fpi == NULL ) || ( envelop_fpo == NULL ) ) {
        XPRINT_ERR( 637, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // Read and write the specified length of data from the input file to the output file
    do {
        bytes_read = fread( &c, sizeof( uint8_t ), 1, encoded_fpi );
        if ( bytes_read > 0 ) {
            bytes_to_write = bytes_read;

            // write buffer with steganography
            for ( i = 0; i < bytes_to_write; i++ ) {
                if ( 1 == fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {

                    out32 = steg_encode( c, tmp32 );

                    if ( 1 != fwrite( ( uint8_t * ) & out32, sizeof( uint32_t ), 1, envelop_fpo ) ) {
                        XPRINT_ERR( 635, XERR_IO_MSG );
                        return XERR_IO;
                    }

                }

            }

        }

    } while ( bytes_read > 0 && !feof( encoded_fpi ) && !feof( envelop_fpi ) && !ferror( envelop_fpo ) );

    // copy the rest of the envelop
    do {
        bytes_read = fread( buffer, 1, 4096, envelop_fpi );
        if ( bytes_read > 0 ) {
            bytes_written = fwrite( buffer, 1, bytes_read, envelop_fpo );
            if ( bytes_written != bytes_read ) {
                XPRINT_ERR( 636, XERR_IO_MSG );
                return XERR_IO;
            }

        }

    } while ( bytes_read > 0 && !feof( envelop_fpi ) && !ferror( envelop_fpo ) );

    return final_ret;
}

int xrn_extract_steg_raw( FILE * envelop_fpi, FILE * block_fo
 )
{

    XPRINT_DEB(  );

    uint32_t tmp32;
    uint8_t out8;
    size_t bytes_read;
    int final_ret;

    final_ret = XSUCCESS;

    if ( ( envelop_fpi == NULL ) || ( block_fo == NULL ) ) {
        XPRINT_ERR( 629, XERR_NULL_MSG );
        return XERR_NULL;
    }

    while ( ( bytes_read = fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) > 0 ) {

        if ( bytes_read == 1 ) {

            out8 = steg_decode( tmp32 );

            // write header
            if ( 1 != fwrite( &out8, sizeof( out8 ), 1, block_fo ) ) {
                XPRINT_ERR( 631, XERR_IO_MSG );
                return XERR_IO;
            }

        }

    }

    return final_ret;

}

int xrn_make_steg_block( FILE * encoded_fpi, FILE * envelop_fpi, FILE * envelop_fpo, uint8_t folding_en,
                         uint32_t tag, uint64_t offset, uint64_t length, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint8_t buffer[4096];
    size_t bytes_read;
    size_t bytes_written;
    size_t bytes_to_write;
    uint32_t crc;
    uint64_t capacity;
    uint8_t crc8;
    uint8_t encoding_guard_tmp[256];
    uint32_t tmp32, out32;
    xrn_encoding_param_t enc_param;
    xrn_encoding_tmp_param_t enc_tmp;
    int i, fold;
    int ret, final_ret;

    header_block_t header;

    final_ret = XSUCCESS;

    if ( ( encoded_fpi == NULL ) || ( envelop_fpi == NULL ) || ( envelop_fpo == NULL ) ) {
        XPRINT_ERR( 71, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( ( folding_en != 0 ) && ( folding_en != 1 ) ) {
        XPRINT_ERR( 1171, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1072, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize encoding decoding param
    ret = xrn_initialize_encoding_parameters( &enc_param, settings.encoding_settings.o_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 802, XERR_GENERAL_MSG );
        return ret;
    }

    crc = 0xffffffff;

    // determine the file size
    if ( 0 != fseek( encoded_fpi, 0, SEEK_END ) ) {
        XPRINT_ERR( 74, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( header ); i++ ) {
        ( ( uint8_t * ) & header )[i] = 0;
    }

    header.total_length = ( uint64_t ) ftell( encoded_fpi );

    if ( 0 != fseek( encoded_fpi, 0, SEEK_SET ) ) {
        XPRINT_ERR( 77, XERR_IO_MSG );
        return XERR_IO;
    }

    // validate the offset and length
    if ( ( length < 0 ) || ( offset < 0 ) || ( offset + length > header.total_length ) ) {
        XPRINT_ERR( 89, XERR_IO_MSG );
        return XERR_IO;
    }

    // get envelop capacity
    if ( XSUCCESS != xrn_estimate_steg_block_length( envelop_fpi, folding_en, &capacity ) ) {
        XPRINT_ERR( 789, XERR_IO_MSG );
        return XERR_IO;
    }

    // check if the envelop is big enough for the block

    if ( ( folding_en == 1 ) && ( length < 256 ) ) {
        if ( capacity < length + 256 ) {
            XPRINT_ERR( 1173, XERR_IO_MSG );
            return XERR_IO;
        }

    } else {
        if ( capacity < length ) {
            XPRINT_ERR( 1177, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // seek to the specified offset in the input file
    if ( 0 != fseek( encoded_fpi, ( long int ) offset, SEEK_SET ) ) {
        XPRINT_ERR( 91, XERR_IO_MSG );
        return XERR_IO;
    }

    // create encoding guard from encoded file
    fold = 0;
    if ( ( length > 256 ) && ( folding_en == 1 ) ) {
        if ( 256 != fread( ( void * ) &encoding_guard_tmp[0], sizeof( uint8_t ), 256, encoded_fpi ) ) {
            XPRINT_ERR( 799, XERR_IO_MSG );
            return XERR_IO;
        }

        // calculate crc
        xrn_crc32( ( uint8_t * ) & encoding_guard_tmp[0], 256, &crc );

        fold = 1;

        // create encoding guard randomly
    } else {

        if ( XSUCCESS != get_random_bytes( ( uint8_t * ) & encoding_guard_tmp[0], 256 ) ) {
            XPRINT_ERR( 800, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // encode encoding_guard
    ret = xrn_encode( &enc_param, encoding_guard_tmp, encoding_guard_tmp, 256, &enc_tmp );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {

        XPRINT_ERR( 806, XERR_GENERAL_MSG );
        return ret;
    }

    // generate steganography encoding_guard
    for ( i = 0; i < 256; i++ ) {

        if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {
            XPRINT_ERR( 801, XERR_IO_MSG );
            return XERR_IO;
        }

        out32 = steg_encode( encoding_guard_tmp[i], tmp32 );

        if ( 1 != fwrite( ( uint8_t * ) & out32, sizeof( uint32_t ), 1, envelop_fpo ) ) {
            XPRINT_ERR( 805, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // write the magic number to the output file

    if ( folding_en == 0 ) {
        header.magic_number = XRN_MAGIC_NUMBER_BLOCK;
    } else {
        header.magic_number = XRN_MAGIC_NUMBER_ENCODED_BLOCK;
    }

    header.tag = tag;
    header.offset = offset;
    header.length = length;
    header.crc8 = 0xff;
    crc8 = 0xff;
    xrn_crc8( ( uint8_t * ) & header, sizeof( header ) - 1, &crc8 );
    header.crc8 = crc8;

    // encode header

    ret =
        xrn_encode( &enc_param, ( uint8_t * ) & header, ( uint8_t * ) & header, sizeof( header ), &enc_tmp );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {

        XPRINT_ERR( 809, XERR_GENERAL_MSG );
        return ret;
    }

    // write header with steganography

    for ( i = 0; i < sizeof( header ); i++ ) {

        if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {
            XPRINT_ERR( 90, XERR_IO_MSG );
            return XERR_IO;
        }

        out32 = steg_encode( ( ( uint8_t * ) & header )[i], tmp32 );

        if ( 1 != fwrite( ( uint8_t * ) & out32, sizeof( uint32_t ), 1, envelop_fpo ) ) {
            XPRINT_ERR( 811, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    if ( fold == 1 ) {
        length = length - 256;
    }

    // Read and write the specified length of data from the input file to the output file
    while ( ( bytes_read = fread( buffer, sizeof( uint8_t ), sizeof( buffer ), encoded_fpi ) ) > 0
            && length > 0 ) {

        bytes_to_write = ( bytes_read < length ) ? bytes_read : length;

        // calculate crc
        xrn_crc32( buffer, ( int ) bytes_to_write, &crc );

        // encode buffer

        ret = xrn_encode( &enc_param, ( uint8_t * ) buffer, ( uint8_t * ) buffer, bytes_to_write, &enc_tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XPRINT_ERR( 812, XERR_GENERAL_MSG );
            return ret;
        }

        // write buffer with steganography

        for ( i = 0; i < bytes_to_write; i++ ) {

            if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {

                XPRINT_ERR( 810, XERR_IO_MSG );
                return XERR_IO;
            }

            out32 = steg_encode( buffer[i], tmp32 );

            if ( 1 != fwrite( ( uint8_t * ) & out32, sizeof( uint32_t ), 1, envelop_fpo ) ) {

                XPRINT_ERR( 813, XERR_IO_MSG );
                return XERR_IO;
            }

        }

        length -= bytes_to_write;

    }

    // encode crc

    ret = xrn_encode( &enc_param, ( uint8_t * ) & crc, ( uint8_t * ) & crc, sizeof( crc ), &enc_tmp );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {

        XPRINT_ERR( 816, XERR_GENERAL_MSG );
        return ret;
    }

    // write buffer with steganography

    for ( i = 0; i < sizeof( uint32_t ); i++ ) {

        if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {
            XPRINT_ERR( 1009, XERR_IO_MSG );
            return XERR_IO;
        }

        out32 = steg_encode( ( ( uint8_t * ) & crc )[i], tmp32 );

        if ( 1 != fwrite( ( uint8_t * ) & out32, sizeof( uint32_t ), 1, envelop_fpo ) ) {
            XPRINT_ERR( 1054, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // copy the rest of the envelop

    while ( ( bytes_read = fread( buffer, 1, 4096, envelop_fpi ) ) > 0 ) {
        bytes_written = fwrite( buffer, 1, bytes_read, envelop_fpo );
        if ( bytes_written != bytes_read ) {
            XPRINT_ERR( 1200, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    return final_ret;
}

int xrn_extract_steg_block( FILE * envelop_fpi, FILE * block_fo, xrn_crypto_extra_settings_t settings
 )
{

    XPRINT_DEB(  );

    uint8_t folding_en, encoding_guard_tmp[256];
    uint32_t tmp32, crc, crc_stored;
    uint64_t total_length;
    uint8_t out8, crc8_stored, crc8;
    int ret, final_ret, i;
    header_block_t header;
    xrn_encoding_param_t enc_param;
    xrn_encoding_tmp_param_t enc_tmp;

    final_ret = XSUCCESS;
    crc = 0xffffffff;

    if ( ( envelop_fpi == NULL ) || ( block_fo == NULL ) ) {
        XPRINT_ERR( 1074, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 768, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize encoding decoding param
    ret = xrn_initialize_encoding_parameters( &enc_param, settings.encoding_settings.i_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1071, XERR_GENERAL_MSG );
        return ret;
    }

    // fetch encoding guard
    for ( i = 0; i < 256; i++ ) {

        if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {
            XPRINT_ERR( 1053, XERR_IO_MSG );
            return XERR_IO;
        }

        out8 = steg_decode( tmp32 );

        // encode crc

        ret = xrn_decode( &enc_param, &out8, &out8, 1, &enc_tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XPRINT_ERR( 1051, XERR_GENERAL_MSG );
            return ret;
        }

        encoding_guard_tmp[i] = out8;

    }

    // fetch header
    for ( i = 0; i < sizeof( header ); i++ ) {

        if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {
            XPRINT_ERR( 1050, XERR_IO_MSG );
            return XERR_IO;
        }

        out8 = steg_decode( tmp32 );

        // decode

        ret = xrn_decode( &enc_param, &out8, &out8, 1, &enc_tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XPRINT_ERR( 993, XERR_GENERAL_MSG );
            return ret;
        }

        ( ( uint8_t * ) & header )[i] = out8;

    }

    crc8_stored = header.crc8;
    header.crc8 = 0xff;
    crc8 = 0xff;
    xrn_crc8( ( uint8_t * ) & header, sizeof( header ) - 1, &crc8 );

    if ( crc8_stored != crc8 ) {
        XPRINT_ERR( 1150, XERR_CRC_MSG );
        return XERR_CRC;
    }

    header.crc8 = crc8_stored;

    if ( header.magic_number == XRN_MAGIC_NUMBER_ENCODED_BLOCK ) {
        folding_en = 1;
        header.magic_number = XRN_MAGIC_NUMBER_BLOCK;
        header.crc8 = 0xff;
        crc8 = 0xff;
        xrn_crc8( ( uint8_t * ) & header, sizeof( header ) - 1, &crc8 );
        header.crc8 = crc8;
    } else {
        folding_en = 0;
    }

    // write header
    if ( 1 != fwrite( ( uint8_t * ) & header, sizeof( header ), 1, block_fo ) ) {
        XPRINT_ERR( 108, XERR_IO_MSG );
        return XERR_IO;
    }

    // unfold
    if ( ( header.length > 256 ) && ( folding_en == 1 ) ) {

        xrn_crc32( ( uint8_t * ) & encoding_guard_tmp[0], 256, &crc );

        if ( 256 != fwrite( encoding_guard_tmp, sizeof( uint8_t ), 256, block_fo ) ) {
            XPRINT_ERR( 1158, XERR_IO_MSG );
            return XERR_IO;
        }

        total_length = header.length - 256 + 4;

    } else {

        total_length = header.length + 4;

    }

    for ( i = 0; i < total_length; i++ ) {

        if ( 1 != fread( ( uint8_t * ) & tmp32, sizeof( uint32_t ), 1, envelop_fpi ) ) {
            XPRINT_ERR( 817, XERR_IO_MSG );
            return XERR_IO;
        }

        out8 = steg_decode( tmp32 );

        // encode crc

        ret = xrn_decode( &enc_param, &out8, &out8, 1, &enc_tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XPRINT_ERR( 823, XERR_GENERAL_MSG );
            return ret;
        }

        if ( i < total_length - 4 ) {
            xrn_crc32( &out8, 1, &crc );
        } else {
            ( ( uint8_t * ) & crc_stored )[3 - ( total_length - ( uint64_t ) i - ( uint64_t ) 1 )] = out8;
        }

        // write header
        if ( 1 != fwrite( &out8, sizeof( out8 ), 1, block_fo ) ) {
            XPRINT_ERR( 822, XERR_IO_MSG );
            return XERR_IO;
        }

        if ( i == total_length - 1 ) {
            if ( crc_stored != crc ) {
                XPRINT_ERR( 1166, XERR_CRC_MSG );
                return XERR_CRC;
            }

        }

    }

    return final_ret;

}

int xrn_decode_encode_wrapper( FILE * input_file_fpr, FILE * encoded_file_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret;
    xrn_encoding_interface_t enc_interface;
    xrn_encoding_tmp_param_t tmp;

    uint64_t num_bytes;
    uint64_t state_size;
    uint64_t state_size_bytes;
    xstate_t state;

    if ( ( input_file_fpr == NULL ) || ( encoded_file_fpw == NULL ) ) {
        XPRINT_ERR( 280, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 281, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize encoding interface

    ret = xrn_initialize_encoding_interface( &enc_interface, settings.encoding_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 282, XERR_GENERAL_MSG );
        return ret;
    }

    // read the entire file

    if ( XNBITS == 256 ) {
        settings.state_size = 32;
    } else {
        settings.state_size = 64;
    }

    state_size = ( uint64_t ) settings.state_size + 1;
    state_size_bytes = sizeof( xnum_t ) * ( uint64_t ) state_size;
    state.xnums = ( xnum_t * ) malloc( state_size_bytes );
    if ( state.xnums == NULL ) {
        XPRINT_ERR( 283, XERR_NULL_MSG );
        return XERR_NULL;
    }

    num_bytes =
        ( uint64_t ) fread( ( uint8_t * ) & state.xnums[0], sizeof( uint8_t ), state_size_bytes,
                            input_file_fpr );

    if ( ferror( input_file_fpr ) ) {
        XRN_FREE_XSTATE( state.xnums, settings.state_size );
        XPRINT_ERR( 284, XERR_IO_MSG );
        return XERR_IO;
    }

    while ( num_bytes > 0 ) {

        ret =
            xrn_decode( &enc_interface.i_encoding_param, ( uint8_t * ) & state.xnums[0],
                        ( uint8_t * ) & state.xnums[0], num_bytes, &tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XRN_FREE_XSTATE( state.xnums, settings.state_size );
            XPRINT_ERR( 285, XERR_GENERAL_MSG );
            return ret;
        }

        ret =
            xrn_encode( &enc_interface.o_encoding_param, ( uint8_t * ) & state.xnums[0],
                        ( uint8_t * ) & state.xnums[0], num_bytes, &tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XRN_FREE_XSTATE( state.xnums, settings.state_size );
            XPRINT_ERR( 658, XERR_GENERAL_MSG );
            return ret;
        }

        if ( num_bytes != fwrite( &state.xnums[0], sizeof( uint8_t ), num_bytes, encoded_file_fpw ) ) {
            XRN_FREE_XSTATE( state.xnums, settings.state_size );
            XPRINT_ERR( 286, XERR_IO_MSG );
            return XERR_IO;
        }

        if ( ferror( encoded_file_fpw ) ) {
            XRN_FREE_XSTATE( state.xnums, settings.state_size );
            XPRINT_ERR( 287, XERR_IO_MSG );
            return XERR_IO;
        }

        num_bytes = ( uint64_t )
            fread( ( uint8_t * ) & state.xnums[0], sizeof( uint8_t ), state_size_bytes, input_file_fpr );

        if ( ferror( input_file_fpr ) ) {
            XRN_FREE_XSTATE( state.xnums, settings.state_size );
            XPRINT_ERR( 288, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    XRN_FREE_XSTATE( state.xnums, settings.state_size );
    return final_ret;

}

int xrn_permute_matrix_compressed_key_wrapper( FILE * xrn_matrix_compressed_fpr,
                                               FILE * xrn_matrix_fpr,
                                               FILE * xmonomial_key_fpr,
                                               FILE * xrn_matrix_compressed_fpw,
                                               xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t monomial_key;
    xrn_matrix_compressed_t xmc;
    xrn_matrix_compressed_t xmc_o;
    int ret, final_ret;

    if ( ( xrn_matrix_compressed_fpr == NULL ) || ( xrn_matrix_fpr == NULL )
         || ( xrn_matrix_compressed_fpw == NULL ) || ( xmonomial_key_fpr == NULL ) ) {
        XPRINT_ERR( 289, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 290, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load monomial key
    ret = xrn_load_monomial_key( &monomial_key, xmonomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 291, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 292, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 293, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_matrix_compressed( xrn_matrix_compressed_fpr, &xmc, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 294, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_permute_matrix_compressed_key( &xmc, xrn_matrix, monomial_key, &xmc_o, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 295, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    ret = xrn_dump_matrix_compressed( &xmc_o, xrn_matrix_compressed_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 296, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_permute_matrix_compressed_key( xrn_matrix_compressed_t * in_xrn_matrix_compressed,
                                       xrn_matrix_t * xrn_matrix,
                                       xmonomial_key_t monomial_key,
                                       xrn_matrix_compressed_t * out_xrn_matrix_compressed,
                                       xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );
    xrn_point_t cos, cob;
    int ret, final_ret, valid_compressed, valid_decompressed, warning_disabled, errors_disabled;
    xrn_matrix_compressed_t tmp_xmc;
    xrn_matrix_t *xm;
    int i = 0;
    xrn_log_t xlog2;

    if ( ( in_xrn_matrix_compressed == NULL ) || ( xrn_matrix == NULL )
         || ( out_xrn_matrix_compressed == NULL ) ) {
        XPRINT_ERR( 297, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( tmp_xmc ); i++ ) {
        ( ( uint8_t * ) & tmp_xmc )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 298, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 299, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;

    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 300, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 301, XERR_GENERAL_MSG );
            return ret;
        }

    }

    cos.point = in_xrn_matrix_compressed->change_of_sign;
    cob.point = in_xrn_matrix_compressed->change_of_base;

    xm = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );
    if ( xm == NULL ) {
        XPRINT_ERR( 302, XERR_NULL_MSG );
        return XERR_NULL;
    }

    valid_compressed = 0;
    valid_decompressed = 0;

    while ( ( valid_compressed == 0 ) || ( valid_decompressed == 0 ) ) {

        valid_compressed = 0;
        valid_decompressed = 0;

        // compute prng
        ret = xrn_generate_confidential_pseudo_random_number( cos, monomial_key, xrn_matrix, &cos, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XRN_FREE( xm );
            XPRINT_ERR( 303, XERR_GENERAL_MSG );
            return ret;
        }

        ret = xrn_generate_confidential_pseudo_random_number( cob, monomial_key, xrn_matrix, &cob, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XRN_FREE( xm );
            XPRINT_ERR( 304, XERR_GENERAL_MSG );
            return ret;
        }

        tmp_xmc.xgenesis_base = in_xrn_matrix_compressed->xgenesis_base;
        tmp_xmc.change_of_sign = cos.point;
        tmp_xmc.change_of_base = cob.point;

        warning_disabled = 0;
        errors_disabled = 0;

        if ( xlog.war_en == 1 ) {
            xlog.war_en = 0;
            warning_disabled = 1;
        }

        if ( xlog.err_en == 1 ) {
            xlog.err_en = 0;
            errors_disabled = 1;
        }

        ret = xrn_matrix_compressed_check( &tmp_xmc );
        if ( ret == XSUCCESS ) {
            valid_compressed = 1;
        }

        xrn_matrix_decompress( &tmp_xmc, xm );

        xlog2 = xlog;
        xlog.not_en = 0;
        ret = xrn_matrix_check( xm );
        xlog = xlog2;
        if ( ( ret == XSUCCESS ) || ( ret == XINFO_PERMUTED_MATRIX ) ) {
            valid_decompressed = 1;
        }

        if ( warning_disabled == 1 ) {
            xlog.war_en = 1;
        }

        if ( errors_disabled == 1 ) {
            xlog.err_en = 1;
        }

    }

    XRN_FREE( xm );
    *out_xrn_matrix_compressed = tmp_xmc;

    return final_ret;

}

int xrn_permute_matrix_compressed_deterministically_wrapper( FILE * xrn_matrix_compressed_fpr,
                                                             FILE * xrn_matrix_fpr,
                                                             FILE * xrn_matrix_compressed_fpw,
                                                             xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xrn_matrix_compressed_t xmc;
    xrn_matrix_compressed_t xmc_o;
    int ret, final_ret;

    if ( ( xrn_matrix_compressed_fpr == NULL ) || ( xrn_matrix_fpr == NULL )
         || ( xrn_matrix_compressed_fpw == NULL ) ) {
        XPRINT_ERR( 305, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 306, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 307, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 308, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_matrix_compressed( xrn_matrix_compressed_fpr, &xmc, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 309, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_permute_matrix_compressed_deterministically( &xmc, xrn_matrix, &xmc_o, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 310, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    ret = xrn_dump_matrix_compressed( &xmc_o, xrn_matrix_compressed_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 311, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_permute_matrix_compressed_deterministically( xrn_matrix_compressed_t * in_xrn_matrix_compressed,
                                                     xrn_matrix_t * xrn_matrix,
                                                     xrn_matrix_compressed_t * out_xrn_matrix_compressed,
                                                     xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );
    xhash_t hash_cos, hash_cob;
    int ret, final_ret, valid_compressed, valid_decompressed, errors_disabled, warning_disabled;
    xrn_matrix_compressed_t tmp_xmc;
    xrn_matrix_t *xm;
    int i;
    xrn_log_t xlog2;

    if ( ( in_xrn_matrix_compressed == NULL ) || ( xrn_matrix == NULL )
         || ( out_xrn_matrix_compressed == NULL ) ) {
        XPRINT_ERR( 312, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( tmp_xmc ); i++ ) {
        ( ( uint8_t * ) & tmp_xmc )[i] = 0;
    }

    final_ret = XSUCCESS;
    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 313, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 314, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 315, XERR_GENERAL_MSG );
            return ret;
        }

    }

    xm = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );
    if ( xm == NULL ) {
        XPRINT_ERR( 316, XERR_NULL_MSG );
        return XERR_NULL;
    }

    valid_compressed = 0;
    valid_decompressed = 0;
    while ( ( valid_compressed == 0 ) || ( valid_decompressed == 0 ) ) {
        valid_compressed = 0;
        valid_decompressed = 0;
        // compute hash
        ret =
            xrn_make_hash_bytes( ( uint8_t * ) ( &in_xrn_matrix_compressed->change_of_sign ),
                                 sizeof( in_xrn_matrix_compressed->change_of_sign ), xrn_matrix, &hash_cos,
                                 settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XRN_FREE( xm );
            XPRINT_ERR( 317, XERR_GENERAL_MSG );
            return ret;
        }

        ret =
            xrn_make_hash_bytes( ( uint8_t * ) ( &in_xrn_matrix_compressed->change_of_base ),
                                 sizeof( in_xrn_matrix_compressed->change_of_base ), xrn_matrix, &hash_cob,
                                 settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XRN_FREE( xm );
            XPRINT_ERR( 318, XERR_GENERAL_MSG );
            return ret;
        }

        tmp_xmc.xgenesis_base = in_xrn_matrix_compressed->xgenesis_base;
        tmp_xmc.change_of_sign = hash_cos.value;
        tmp_xmc.change_of_base = hash_cob.value;

        errors_disabled = 0;
        warning_disabled = 0;
        if ( xlog.war_en == 1 ) {
            xlog.war_en = 0;
            warning_disabled = 1;
        }

        if ( xlog.err_en == 1 ) {
            xlog.err_en = 0;
            errors_disabled = 1;
        }

        ret = xrn_matrix_compressed_check( &tmp_xmc );
        if ( ret == XSUCCESS ) {
            valid_compressed = 1;
        }

        xrn_matrix_decompress( &tmp_xmc, xm );

        xlog2 = xlog;
        xlog.not_en = 0;
        ret = xrn_matrix_check( xm );
        xlog = xlog2;
        if ( ( ret == XSUCCESS ) || ( ret == XINFO_PERMUTED_MATRIX ) ) {
            valid_decompressed = 1;
        }

        if ( warning_disabled == 1 ) {
            xlog.war_en = 1;
        }

        if ( errors_disabled == 1 ) {
            xlog.err_en = 1;
        }

    }

    XRN_FREE( xm );
    *out_xrn_matrix_compressed = tmp_xmc;

    return final_ret;

}

int xrn_make_monovalent_key_wrapper( FILE * xrn_matrix_fpr, uint64_t start_timestamp, uint64_t end_timestamp,
                                     FILE * polyvalent_key_fpw, FILE * polyvalent_proof_fpw,
                                     FILE * monovalent_key_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xpolyvalent_key_t xpoly_key;
    xmonovalent_key_t xmono_key;
    xpolyvalent_proof_t xpoly_proof;
    int final_ret, ret, i;

    if ( ( xrn_matrix_fpr == NULL ) || ( polyvalent_key_fpw == NULL )
         || ( polyvalent_proof_fpw == NULL ) || ( monovalent_key_fpw == NULL ) ) {
        XPRINT_ERR( 319, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( end_timestamp <= start_timestamp ) {
        XPRINT_ERR( 55, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( xpoly_key ); i++ ) {
        ( ( uint8_t * ) & xpoly_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( xmono_key ); i++ ) {
        ( ( uint8_t * ) & xmono_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( xpoly_proof ); i++ ) {
        ( ( uint8_t * ) & xpoly_proof )[i] = 0;
    }

    final_ret = XSUCCESS;

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 320, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 321, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_make_monovalent_key( xrn_matrix, start_timestamp, end_timestamp, &xpoly_key, &xpoly_proof,
                                 &xmono_key, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 322, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_polyvalent_key( xpoly_key, polyvalent_key_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 323, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_polyvalent_proof( xpoly_proof, polyvalent_proof_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 324, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_monovalent_key( xmono_key, monovalent_key_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 325, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;
}

int xrn_make_monovalent_key( xrn_matrix_t * xrn_matrix, uint64_t start_timestamp, uint64_t end_timestamp,
                             xpolyvalent_key_t * polyvalent_key, xpolyvalent_proof_t * polyvalent_proof,
                             xmonovalent_key_t * monovalent_key, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret, i;
    xnum_t xnum_validity;
    xpolyvalent_key_t polyvalent_key_local;
    xpolyvalent_proof_t polyvalent_proof_local;
    xmonovalent_key_t monovalent_key_local;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( polyvalent_proof == NULL ) || ( polyvalent_key == NULL )
         || ( monovalent_key == NULL ) ) {
        XPRINT_ERR( 326, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( end_timestamp <= start_timestamp ) {
        XPRINT_ERR( 58, XERR_IO_MSG );
        return XERR_IO;
    }

    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 0;

    for ( i = 0; i < sizeof( polyvalent_key_local ); i++ ) {
        ( ( uint8_t * ) & polyvalent_key_local )[i] = 0;
    }

    for ( i = 0; i < sizeof( polyvalent_proof_local ); i++ ) {
        ( ( uint8_t * ) & polyvalent_proof_local )[i] = 0;
    }

    for ( i = 0; i < sizeof( monovalent_key_local ); i++ ) {
        ( ( uint8_t * ) & monovalent_key_local )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 327, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 328, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 329, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    monovalent_key_local.start_timestamp = start_timestamp;
    monovalent_key_local.end_timestamp = end_timestamp;

    // make polyvalent_key
    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

        // generate confidential key

        ret = XERR_SPARSE_MKEY;
        while ( ret == XERR_SPARSE_MKEY ) {

            ret = xrn_initialize_true_rnd_num( settings.rnd_str, &polyvalent_key_local.state[i] );

            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 330, XERR_GENERAL_MSG );
                return XERR_GENERAL;
            }

            // check key sparsity

            ret = xrn_check_sparsity( polyvalent_key_local.state[i] );

        }

    }

    // initialize validity
    for ( i = 0; i < sizeof( start_timestamp ); i++ ) {
        ( ( uint8_t * ) & xnum_validity )[i] = ( ( uint8_t * ) & start_timestamp )[i];
    }

    for ( i = sizeof( start_timestamp ); i < sizeof( end_timestamp ) + sizeof( start_timestamp ); i++ ) {
        ( ( uint8_t * ) & xnum_validity )[i] =
            ( ( uint8_t * ) & end_timestamp )[i - ( int ) sizeof( start_timestamp )];
    }

    for ( i = sizeof( start_timestamp ) + sizeof( end_timestamp ); i < sizeof( xnum_t ); i++ ) {
        ( ( uint8_t * ) & xnum_validity )[i] = 0;
    }

    if ( settings.thread_enable == 0 ) {

        // compute proof
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

            ret =
                xrn_matrix_traverse( xrn_matrix, &xnum_validity, &polyvalent_key_local.state[i],
                                     &polyvalent_proof_local.state[i], &constant_execution,
                                     &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 331, XERR_GENERAL_MSG );
                return ret;
            }

        }

        // compute monovalent keys
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {

            ret =
                xrn_matrix_traverse( xrn_matrix, &polyvalent_proof_local.state[i],
                                     &polyvalent_proof_local.state[i + 1],
                                     &monovalent_key_local.state[i], &constant_execution, &force_linearity,
                                     &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 332, XERR_GENERAL_MSG );
                return ret;
            }

            ret =
                xrn_matrix_traverse( xrn_matrix, &polyvalent_proof_local.state[i + 1],
                                     &polyvalent_proof_local.state[i],
                                     &monovalent_key_local.state[i + 1], &constant_execution,
                                     &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 333, XERR_GENERAL_MSG );
                return ret;
            }

        }

    } else {

        cmtraverse_t arg[XRN_STATE_KEY_SIZE];
        int ret_thread[XRN_STATE_KEY_SIZE];

#if XRN_GNU_LINUX == 1
        pthread_t threads[XRN_STATE_KEY_SIZE];
#else
        HANDLE threads[XRN_STATE_KEY_SIZE];
        unsigned threadID[XRN_STATE_KEY_SIZE];
#endif

        // compute proof
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
            ret_thread[i] = 0;
            arg[i].xm = xrn_matrix;
            arg[i].p = &xnum_validity;
            arg[i].d = &polyvalent_key_local.state[i];
            arg[i].dst = &polyvalent_proof_local.state[i];
            arg[i].linear = &ret_thread[i];
            arg[i].constant_execution = &constant_execution;
            arg[i].force_linearity = &force_linearity;
            arg[i].check_sparcity = &check_sparcity;

#if XRN_GNU_LINUX == 1
            if ( 0 != pthread_create( &threads[i], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i] ) ) {
                XPRINT_ERR( 334, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 335, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

#else
            if ( ( threads[i] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                           xrn_matrix_traverse_pthread,
                                                           ( void * ) &arg[i], 0, &threadID[i] ) ) == 0 ) {
                XPRINT_ERR( 336, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 337, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

#endif
        }

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

#if XRN_GNU_LINUX == 1
            pthread_join( threads[i], NULL );
#else
            WaitForSingleObject( threads[i], INFINITE );
#endif
        }

        // compute monovalent keys
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {

            ret_thread[i] = 0;
            arg[i].p = &polyvalent_proof_local.state[i];
            arg[i].d = &polyvalent_proof_local.state[i + 1];
            arg[i].dst = &monovalent_key_local.state[i];
            arg[i].linear = &ret_thread[i];
            arg[i].constant_execution = &constant_execution;
            arg[i].force_linearity = &force_linearity;
            arg[i].check_sparcity = &check_sparcity;

            ret_thread[i + 1] = 0;
            arg[i + 1].p = &polyvalent_proof_local.state[i + 1];
            arg[i + 1].d = &polyvalent_proof_local.state[i];
            arg[i + 1].dst = &monovalent_key_local.state[i + 1];
            arg[i + 1].linear = &ret_thread[i + 1];
            arg[i + 1].constant_execution = &constant_execution;
            arg[i + 1].force_linearity = &force_linearity;
            arg[i + 1].check_sparcity = &check_sparcity;

#if XRN_GNU_LINUX == 1
            if ( 0 != pthread_create( &threads[i], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i] ) ) {
                XPRINT_ERR( 338, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 339, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( 0 != pthread_create( &threads[i + 1], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i + 1] ) ) {
                XPRINT_ERR( 340, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 341, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#else
            if ( ( threads[i] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                           xrn_matrix_traverse_pthread,
                                                           ( void * ) &arg[i], 0, &threadID[i] ) ) == 0 ) {
                XPRINT_ERR( 342, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 343, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( ( threads[i + 1] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                               xrn_matrix_traverse_pthread,
                                                               ( void * ) &arg[i + 1], 0,
                                                               &threadID[i + 1] ) ) == 0 ) {
                XPRINT_ERR( 344, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 345, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#endif

        }

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

#if XRN_GNU_LINUX == 1
            pthread_join( threads[i], NULL );
#else
            WaitForSingleObject( threads[i], INFINITE );
            CloseHandle( threads[i] );
#endif
        }

    }

    *polyvalent_key = polyvalent_key_local;
    *polyvalent_proof = polyvalent_proof_local;
    *monovalent_key = monovalent_key_local;

    return final_ret;

}

int xrn_make_commitment_from_binomial_key_wrapper( FILE * xrn_matrix_fpr,
                                                   FILE * binomial_key_fpr,
                                                   FILE * monomial_commitment_fpw,
                                                   FILE * binomial_commitment_fpw,
                                                   xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xbinomial_key_t binomial_key;
    xmonomial_commitment_t monomial_commitment;
    xbinomial_commitment_t binomial_commitment;
    int i, ret, final_ret;
    xrn_matrix_t *xrn_matrix;

    if ( ( xrn_matrix_fpr == NULL ) || ( binomial_key_fpr == NULL ) || ( monomial_commitment_fpw == NULL )
         || ( binomial_commitment_fpw == NULL ) ) {
        XPRINT_ERR( 346, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 347, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    for ( i = 0; i < sizeof( binomial_key ); i++ ) {
        ( ( uint8_t * ) & binomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_commitment ); i++ ) {
        ( ( uint8_t * ) & monomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( binomial_commitment ); i++ ) {
        ( ( uint8_t * ) & binomial_commitment )[i] = 0;
    }

    // load binomial key        

    ret = xrn_load_binomial_key( &binomial_key, binomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 348, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 349, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 350, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_make_commitment_from_binomial_key( binomial_key, xrn_matrix, &monomial_commitment,
                                               &binomial_commitment, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 351, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    ret = xrn_dump_monomial_commitment( monomial_commitment, monomial_commitment_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 352, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_binomial_commitment( binomial_commitment, binomial_commitment_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 353, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_make_commitment_from_binomial_key( xbinomial_key_t binomial_key, xrn_matrix_t * xrn_matrix,
                                           xmonomial_commitment_t * monomial_commitment,
                                           xbinomial_commitment_t * binomial_commitment,
                                           xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret, i;
    xmonomial_commitment_t mc;
    xbinomial_commitment_t bc;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( monomial_commitment == NULL ) || ( binomial_commitment == NULL ) ) {
        XPRINT_ERR( 354, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( bc ); i++ ) {
        ( ( uint8_t * ) & bc )[i] = 0;
    }

    for ( i = 0; i < sizeof( mc ); i++ ) {
        ( ( uint8_t * ) & mc )[i] = 0;
    }

    constant_execution = settings.const_exec_time;
    check_sparcity = 1;
    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 355, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 356, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 357, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // compute monomial commitment

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &mc.distance );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 358, XERR_GENERAL_MSG );
        return ret;
    }

    // compute binomial commitment

    bc.start = binomial_key.start;
    force_linearity = 1;
    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_key.start, &mc.distance, &bc.end, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 359, XERR_GENERAL_MSG );
        return ret;
    }

    // assign outputs

    *monomial_commitment = mc;
    *binomial_commitment = bc;

    return final_ret;
}

int xrn_check_monovalent_key_wrapper( FILE * xrn_matrix_fpr,
                                      FILE * monovalent_key_fpr,
                                      FILE * polyvalent_proof_fpr, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonovalent_key_t monovalent_key;
    xpolyvalent_proof_t polyvalent_proof;
    int ret, final_ret;
    xrn_matrix_t *xrn_matrix;

    if ( ( xrn_matrix_fpr == NULL ) || ( monovalent_key_fpr == NULL )
         || ( polyvalent_proof_fpr == NULL ) ) {
        XPRINT_ERR( 360, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 361, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load monovalent key

    ret = xrn_load_monovalent_key( &monovalent_key, monovalent_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 362, XERR_GENERAL_MSG );
        return ret;
    }

    // load polyvalent_proof key

    ret = xrn_load_polyvalent_proof( &polyvalent_proof, polyvalent_proof_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 363, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 364, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 365, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_monovalent_key( xrn_matrix, &monovalent_key, &polyvalent_proof, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 366, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_check_monovalent_key( xrn_matrix_t * xrn_matrix,
                              xmonovalent_key_t * monovalent_key,
                              xpolyvalent_proof_t * polyvalent_proof, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, neq, ret, final_ret;
    xpolyvalent_proof_t polyvalent_proof_tmp;
    uint8_t force_linearity;
    uint8_t constant_execution;
    uint8_t check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( monovalent_key == NULL )
         || ( polyvalent_proof == NULL ) ) {
        XPRINT_ERR( 367, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    force_linearity = 1;
    constant_execution = settings.const_exec_time;
    check_sparcity = 0;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;

    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 368, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 369, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 370, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( settings.thread_enable == 0 ) {

        // perform proof calculation

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {
            ret =
                xrn_matrix_traverse( xrn_matrix, &polyvalent_proof->state[i],
                                     &polyvalent_proof->state[i + 1], &polyvalent_proof_tmp.state[i],
                                     &constant_execution, &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 371, XERR_GENERAL_MSG );
                return ret;
            }

            ret =
                xrn_matrix_traverse( xrn_matrix, &polyvalent_proof->state[i + 1],
                                     &polyvalent_proof->state[i], &polyvalent_proof_tmp.state[i + 1],
                                     &constant_execution, &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 372, XERR_GENERAL_MSG );
                return ret;
            }

        }

    } else {

        cmtraverse_t arg[XRN_STATE_KEY_SIZE];
        int ret_thread[XRN_STATE_KEY_SIZE];

#if XRN_GNU_LINUX == 1
        pthread_t threads[XRN_STATE_KEY_SIZE];
#else
        HANDLE threads[XRN_STATE_KEY_SIZE];
        unsigned threadID[XRN_STATE_KEY_SIZE];
#endif

        // compute monovalent keys
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {

            ret_thread[i] = 0;
            arg[i].xm = xrn_matrix;
            arg[i].p = &polyvalent_proof->state[i];
            arg[i].d = &polyvalent_proof->state[i + 1];
            arg[i].dst = &polyvalent_proof_tmp.state[i];
            arg[i].linear = &ret_thread[i];
            arg[i].constant_execution = &constant_execution;
            arg[i].force_linearity = &force_linearity;
            arg[i].check_sparcity = &check_sparcity;

            ret_thread[i + 1] = 0;
            arg[i + 1].xm = xrn_matrix;
            arg[i + 1].p = &polyvalent_proof->state[i + 1];
            arg[i + 1].d = &polyvalent_proof->state[i];
            arg[i + 1].dst = &polyvalent_proof_tmp.state[i + 1];
            arg[i + 1].linear = &ret_thread[i + 1];
            arg[i + 1].constant_execution = &constant_execution;
            arg[i + 1].force_linearity = &force_linearity;
            arg[i + 1].check_sparcity = &check_sparcity;

#if XRN_GNU_LINUX == 1

            if ( 0 != pthread_create( &threads[i], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i] ) ) {
                XPRINT_ERR( 373, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 374, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( 0 != pthread_create( &threads[i + 1], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i + 1] ) ) {
                XPRINT_ERR( 375, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 376, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#else
            if ( ( threads[i] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                           xrn_matrix_traverse_pthread,
                                                           ( void * ) &arg[i], 0, &threadID[i] ) ) == 0 ) {
                XPRINT_ERR( 377, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 378, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( ( threads[i + 1] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                               xrn_matrix_traverse_pthread,
                                                               ( void * ) &arg[i + 1], 0,
                                                               &threadID[i + 1] ) ) == 0 ) {
                XPRINT_ERR( 379, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 380, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#endif

        }

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

#if XRN_GNU_LINUX == 1

            pthread_join( threads[i], NULL );

#else
            WaitForSingleObject( threads[i], INFINITE );
            CloseHandle( threads[i] );
#endif
        }

    }

    // perform proof check

    neq = 0;
    for ( i = 0; ( i < XRN_STATE_KEY_SIZE ) && ( neq == 0 ); i++ ) {

        XNUM_CMP( ( monovalent_key->state[i] ), ( polyvalent_proof_tmp.state[i] ), neq );

        if ( neq == 1 ) {

            XPRINT_NOT( 1 );
            final_ret = xrn_store_warnings_in_return_value( ( int ) XWAR_SIG, final_ret );
            return final_ret;
        }

    }

    if ( neq == 0 ) {

        XPRINT_NOT( 0 );
    }

    return final_ret;

}

int xrn_exchange_polyvalent_key_wrapper( FILE * xrn_matrix_fpr,
                                         FILE * internal_monovalent_key_fpr,
                                         FILE * external_monovalent_key_fpr, FILE * polyvalent_key_fpr,
                                         FILE * polyvalent_proof_fpr, FILE * shared_polyvalent_key_fpw,
                                         xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonovalent_key_t internal_monovalent_key;
    xmonovalent_key_t external_monovalent_key;
    xpolyvalent_key_t polyvalent_key;
    xpolyvalent_proof_t polyvalent_proof;
    xpolyvalent_key_t shared_polyvalent_key;
    int ret, final_ret;
    xrn_matrix_t *xrn_matrix;

    if ( ( xrn_matrix_fpr == NULL ) || ( internal_monovalent_key_fpr == NULL )
         || ( polyvalent_proof_fpr == NULL )
         || ( external_monovalent_key_fpr == NULL ) || ( polyvalent_key_fpr == NULL )
         || ( shared_polyvalent_key_fpw == NULL ) ) {
        XPRINT_ERR( 381, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 382, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load data structures

    ret = xrn_load_polyvalent_key( &polyvalent_key, polyvalent_key_fpr, &settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 383, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monovalent_key( &internal_monovalent_key, internal_monovalent_key_fpr, &settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 384, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monovalent_key( &external_monovalent_key, external_monovalent_key_fpr, &settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 385, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_polyvalent_proof( &polyvalent_proof, polyvalent_proof_fpr, &settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 386, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 387, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 388, XERR_GENERAL_MSG );
        return ret;
    }

    // compute exchange

    ret =
        xrn_exchange_polyvalent_key( xrn_matrix, &internal_monovalent_key, &external_monovalent_key,
                                     &polyvalent_key, &polyvalent_proof, &shared_polyvalent_key, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 389, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    // dump output

    ret = xrn_dump_polyvalent_key( shared_polyvalent_key, shared_polyvalent_key_fpw, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 390, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_exchange_polyvalent_key( xrn_matrix_t * xrn_matrix, xmonovalent_key_t * internal_monovalent_key,
                                 xmonovalent_key_t * external_monovalent_key,
                                 xpolyvalent_key_t * polyvalent_key,
                                 xpolyvalent_proof_t * polyvalent_proof,
                                 xpolyvalent_key_t * shared_polyvalent_key,
                                 xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret, i;
    xnum_t tmp0, tmp1;
    uint64_t t;
    xpolyvalent_key_t shared_polyvalent_key_local;
    uint8_t force_linearity;
    uint8_t constant_execution;
    uint8_t check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( internal_monovalent_key == NULL ) || ( polyvalent_proof == NULL )
         || ( external_monovalent_key == NULL ) || ( polyvalent_key == NULL )
         || ( shared_polyvalent_key == NULL ) ) {
        XPRINT_ERR( 391, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    force_linearity = 1;
    constant_execution = settings.const_exec_time;
    check_sparcity = 0;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 392, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 393, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 394, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check timestamps

    if ( ( external_monovalent_key->start_timestamp != internal_monovalent_key->start_timestamp ) ||
         ( external_monovalent_key->end_timestamp != internal_monovalent_key->end_timestamp ) ) {
        XPRINT_ERR( 395, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    if ( 0 > time( ( time_t * ) & t ) ) {
        XPRINT_ERR( 396, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // check time of the certificate

    if ( ( t < internal_monovalent_key->start_timestamp )
         || ( t > internal_monovalent_key->end_timestamp ) ) {
        XPRINT_ERR( 397, XERR_TIMING_MSG );
        return ( int ) XERR_TIMING;
    }

    if ( settings.thread_enable == 0 ) {

        // compute shared key

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {

            ret =
                xrn_matrix_traverse( xrn_matrix, &external_monovalent_key->state[i],
                                     &polyvalent_proof->state[i + 1], &tmp0, &constant_execution,
                                     &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 398, XERR_GENERAL_MSG );
                return ret;
            }

            ret =
                xrn_matrix_traverse( xrn_matrix, &external_monovalent_key->state[i + 1],
                                     &polyvalent_proof->state[i], &tmp1, &constant_execution,
                                     &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 399, XERR_GENERAL_MSG );
                return ret;
            }

            ret =
                xrn_matrix_traverse( xrn_matrix, &tmp0, &polyvalent_key->state[i],
                                     &shared_polyvalent_key_local.state[i], &constant_execution,
                                     &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 400, XERR_GENERAL_MSG );
                return ret;
            }

            ret =
                xrn_matrix_traverse( xrn_matrix, &tmp1, &polyvalent_key->state[i + 1],
                                     &shared_polyvalent_key_local.state[i + 1], &constant_execution,
                                     &force_linearity, &check_sparcity );
            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 401, XERR_GENERAL_MSG );
                return ret;
            }

        }

    } else {

        cmtraverse_t arg[XRN_STATE_KEY_SIZE];
        int ret_thread[XRN_STATE_KEY_SIZE];
        xpolyvalent_key_t tmp_poly;

#if XRN_GNU_LINUX == 1
        pthread_t threads[XRN_STATE_KEY_SIZE];
#else
        HANDLE threads[XRN_STATE_KEY_SIZE];
        unsigned threadID[XRN_STATE_KEY_SIZE];
#endif

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {

            ret_thread[i] = 0;
            arg[i].xm = xrn_matrix;
            arg[i].p = &external_monovalent_key->state[i];
            arg[i].d = &polyvalent_proof->state[i + 1];
            arg[i].dst = &tmp_poly.state[i];
            arg[i].linear = &ret_thread[i];
            arg[i].constant_execution = &constant_execution;
            arg[i].force_linearity = &force_linearity;
            arg[i].check_sparcity = &check_sparcity;

            ret_thread[i + 1] = 0;
            arg[i + 1].xm = xrn_matrix;
            arg[i + 1].p = &external_monovalent_key->state[i + 1];;
            arg[i + 1].d = &polyvalent_proof->state[i];
            arg[i + 1].dst = &tmp_poly.state[i + 1];
            arg[i + 1].linear = &ret_thread[i + 1];
            arg[i + 1].constant_execution = &constant_execution;
            arg[i + 1].force_linearity = &force_linearity;
            arg[i + 1].check_sparcity = &check_sparcity;

#if XRN_GNU_LINUX == 1

            if ( 0 != pthread_create( &threads[i], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i] ) ) {
                XPRINT_ERR( 402, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 403, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( 0 != pthread_create( &threads[i + 1], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i + 1] ) ) {
                XPRINT_ERR( 404, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 405, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#else
            if ( ( threads[i] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                           xrn_matrix_traverse_pthread,
                                                           ( void * ) &arg[i], 0, &threadID[i] ) ) == 0 ) {
                XPRINT_ERR( 406, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 407, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( ( threads[i + 1] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                               xrn_matrix_traverse_pthread,
                                                               ( void * ) &arg[i + 1], 0,
                                                               &threadID[i + 1] ) ) == 0 ) {
                XPRINT_ERR( 408, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 409, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#endif

        }

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

#if XRN_GNU_LINUX == 1
            pthread_join( threads[i], NULL );
#else
            WaitForSingleObject( threads[i], INFINITE );
#endif
        }

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i = i + 2 ) {

            ret_thread[i] = 0;
            arg[i].p = &tmp_poly.state[i];
            arg[i].d = &polyvalent_key->state[i];
            arg[i].dst = &shared_polyvalent_key_local.state[i];
            arg[i].linear = &ret_thread[i];
            arg[i].constant_execution = &constant_execution;
            arg[i].force_linearity = &force_linearity;
            arg[i].check_sparcity = &check_sparcity;

            ret_thread[i + 1] = 0;
            arg[i + 1].p = &tmp_poly.state[i + 1];;
            arg[i + 1].d = &polyvalent_key->state[i + 1];
            arg[i + 1].dst = &shared_polyvalent_key_local.state[i + 1];
            arg[i + 1].linear = &ret_thread[i + 1];
            arg[i + 1].constant_execution = &constant_execution;
            arg[i + 1].force_linearity = &force_linearity;
            arg[i + 1].check_sparcity = &check_sparcity;

#if XRN_GNU_LINUX == 1

            if ( 0 != pthread_create( &threads[i], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i] ) ) {
                XPRINT_ERR( 410, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 411, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( 0 != pthread_create( &threads[i + 1], NULL, xrn_matrix_traverse_pthread, ( void * )
                                      &arg[i + 1] ) ) {
                XPRINT_ERR( 412, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 413, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#else
            if ( ( threads[i] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                           xrn_matrix_traverse_pthread,
                                                           ( void * ) &arg[i], 0, &threadID[i] ) ) == 0 ) {
                XPRINT_ERR( 414, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 415, XERR_GENERAL_MSG );
                return ret_thread[i];
            }

            if ( ( threads[i + 1] = ( HANDLE ) _beginthreadex( NULL, 0, ( unsigned int ( * )( void * ) )
                                                               xrn_matrix_traverse_pthread,
                                                               ( void * ) &arg[i + 1], 0,
                                                               &threadID[i + 1] ) ) == 0 ) {
                XPRINT_ERR( 416, XERR_NULL_MSG );
                return XERR_NULL;
            }

            final_ret = xrn_store_warnings_in_return_value( ret_thread[i + 1], final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 417, XERR_GENERAL_MSG );
                return ret_thread[i + 1];
            }

#endif

        }

        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

#if XRN_GNU_LINUX == 1
            pthread_join( threads[i], NULL );
#else
            WaitForSingleObject( threads[i], INFINITE );
            CloseHandle( threads[i] );
#endif
        }

    }

    *shared_polyvalent_key = shared_polyvalent_key_local;

    return final_ret;

}

int xrn_make_commitment_from_sym_certificate_wrapper( FILE * certificate_fpr, FILE * xrn_matrix_fpr,
                                                      FILE * monomial_commitment_fpw,
                                                      FILE * binomial_commitment_fpw,
                                                      xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret, i;
    xrn_matrix_t *xrn_matrix;
    xcertificate_sym_t certificate_sym;
    xmonomial_commitment_t monomial_commitment;
    xbinomial_commitment_t binomial_commitment;

    if ( ( xrn_matrix_fpr == NULL ) || ( certificate_fpr == NULL ) || ( monomial_commitment_fpw == NULL )
         || ( binomial_commitment_fpw == NULL ) ) {
        XPRINT_ERR( 418, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( monomial_commitment ); i++ ) {
        ( ( uint8_t * ) & monomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( binomial_commitment ); i++ ) {
        ( ( uint8_t * ) & binomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( certificate_sym ); i++ ) {
        ( ( uint8_t * ) & certificate_sym )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 419, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 420, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 421, XERR_GENERAL_MSG );
        return ret;
    }

    // compute commitment

    ret = xrn_load_certificate_sym( &certificate_sym, certificate_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 422, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_make_commitment_from_sym_certificate( certificate_sym, xrn_matrix, &monomial_commitment,
                                                  &binomial_commitment, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 423, XERR_GENERAL_MSG );
        return ret;
    }

    // dump results

    XRN_FREE( xrn_matrix );

    ret = xrn_dump_monomial_commitment( monomial_commitment, monomial_commitment_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 424, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_binomial_commitment( binomial_commitment, binomial_commitment_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 425, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_commitment_from_sym_certificate( xcertificate_sym_t certificate, xrn_matrix_t * xrn_matrix,
                                              xmonomial_commitment_t * monomial_commitment,
                                              xbinomial_commitment_t * binomial_commitment,
                                              xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret, i;
    xhash_t hash;
    xbinomial_key_t binomial_key;
    xrn_log_t xlog2;

    struct certificate_t {
        xmonovalent_key_t monovalent_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( ( xrn_matrix == NULL ) || ( monomial_commitment == NULL ) || ( binomial_commitment == NULL ) ) {
        XPRINT_ERR( 426, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( certificate.end_timestamp <= certificate.start_timestamp ) {
        XPRINT_ERR( 80, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( binomial_key ); i++ ) {
        ( ( uint8_t * ) & binomial_key )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 427, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 428, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 429, XERR_GENERAL_MSG );
            return ret;
        }

    }

    for ( i = 0; i < sizeof( certificate_tmp ); i++ ) {
        ( ( uint8_t * ) & certificate_tmp )[i] = 0;
    }

    certificate_tmp.monovalent_key = certificate.monovalent_key;
    certificate_tmp.start_timestamp = certificate.start_timestamp;
    certificate_tmp.end_timestamp = certificate.end_timestamp;
    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate.subject );

    // compute hash
    ret =
        xrn_make_hash_bytes( ( uint8_t * ) ( &certificate_tmp ), sizeof( certificate_tmp ), xrn_matrix, &hash,
                             settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 430, XERR_GENERAL_MSG );
        return ret;
    }

    binomial_key.start = hash.value;
    binomial_key.end = certificate.signature.proof;

    ret =
        xrn_make_commitment_from_binomial_key( binomial_key, xrn_matrix, monomial_commitment,
                                               binomial_commitment, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 431, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_commitment_from_sym_signatures_wrapper( FILE * plain_text_fpr,
                                                     FILE * xrn_matrix_fpr,
                                                     FILE * signature_fpr,
                                                     FILE * monomial_commitment_fpw,
                                                     FILE * binomial_commitment_fpw,
                                                     xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, ret, final_ret;
    xrn_matrix_t *xrn_matrix;
    xsignature_sym_t signature_sym;
    xmonomial_commitment_t monomial_commitment;
    xbinomial_commitment_t binomial_commitment;

    if ( ( plain_text_fpr == NULL ) || ( xrn_matrix_fpr == NULL ) || ( signature_fpr == NULL )
         || ( monomial_commitment_fpw == NULL )
         || ( binomial_commitment_fpw == NULL ) ) {
        XPRINT_ERR( 446, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( signature_sym ); i++ ) {
        ( ( uint8_t * ) & signature_sym )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_commitment ); i++ ) {
        ( ( uint8_t * ) & monomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( binomial_commitment ); i++ ) {
        ( ( uint8_t * ) & binomial_commitment )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 447, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 448, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 449, XERR_GENERAL_MSG );
        return ret;
    }

    // compute commitment

    ret = xrn_load_signature_sym( &signature_sym, signature_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 450, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_make_commitment_from_sym_signature( plain_text_fpr, xrn_matrix, signature_sym,
                                                &monomial_commitment, &binomial_commitment, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 451, XERR_GENERAL_MSG );
        return ret;
    }

    // dump results

    XRN_FREE( xrn_matrix );

    ret = xrn_dump_monomial_commitment( monomial_commitment, monomial_commitment_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 452, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_binomial_commitment( binomial_commitment, binomial_commitment_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 453, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_commitment_from_sym_signature( FILE * plain_text_fpr,
                                            xrn_matrix_t * xrn_matrix,
                                            xsignature_sym_t signature,
                                            xmonomial_commitment_t * monomial_commitment,
                                            xbinomial_commitment_t * binomial_commitment,
                                            xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret, i;
    xhash_t hash;
    xbinomial_key_t binomial_key;
    xrn_log_t xlog2;

    if ( ( plain_text_fpr == NULL ) || ( xrn_matrix == NULL ) || ( monomial_commitment == NULL )
         || ( binomial_commitment == NULL ) ) {
        XPRINT_ERR( 454, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( binomial_key ); i++ ) {
        ( ( uint8_t * ) & binomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( hash ); i++ ) {
        ( ( uint8_t * ) & hash )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 455, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 456, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 457, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // compute hash
    ret = xrn_make_hash( plain_text_fpr, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 458, XERR_GENERAL_MSG );
        return ret;
    }

    binomial_key.start = hash.value;
    binomial_key.end = signature.proof;

    ret =
        xrn_make_commitment_from_binomial_key( binomial_key, xrn_matrix, monomial_commitment,
                                               binomial_commitment, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 459, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_monomial_response_wrapper( FILE * monomial_response_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_response_t mresponse;
    int i, ret, final_ret;

    if ( monomial_response_fpw == NULL ) {
        XPRINT_ERR( 460, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( mresponse ); i++ ) {
        ( ( uint8_t * ) & mresponse )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 461, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = xrn_make_monomial_response( &mresponse, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 462, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_monomial_response( mresponse, monomial_response_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 463, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_monomial_response( xmonomial_response_t * monomial_response, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, final_ret, ret;
    xmonomial_response_t mresponse;

    if ( monomial_response == NULL ) {
        XPRINT_ERR( 464, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( mresponse ); i++ ) {
        ( ( uint8_t * ) & mresponse )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 465, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // generate confidential monomial key

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &mresponse.distance );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 466, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    *monomial_response = mresponse;

    return final_ret;

}

int xrn_make_monomial_proof_from_signature_wrapper( FILE * plain_text_fpr, FILE * xrn_matrix_fpr,
                                                    FILE * signature_fpr, FILE * monomial_key_fpr,
                                                    FILE * monomial_commitment_fpr,
                                                    FILE * monomial_response_fpr,
                                                    FILE * monomial_proof_fpw,
                                                    xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, ret, final_ret;
    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t monomial_key;
    xsignature_sym_t signature;
    xmonomial_commitment_t monomial_commitment;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;

    if ( ( plain_text_fpr == NULL ) || ( signature_fpr == NULL ) || ( xrn_matrix_fpr == NULL )
         || ( monomial_key_fpr == NULL )
         || ( monomial_commitment_fpr == NULL ) || ( monomial_response_fpr == NULL )
         || ( monomial_proof_fpw == NULL ) ) {
        XPRINT_ERR( 484, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( monomial_key ); i++ ) {
        ( ( uint8_t * ) & monomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( signature ); i++ ) {
        ( ( uint8_t * ) & signature )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_commitment ); i++ ) {
        ( ( uint8_t * ) & monomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_response ); i++ ) {
        ( ( uint8_t * ) & monomial_response )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_proof ); i++ ) {
        ( ( uint8_t * ) & monomial_proof )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 485, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load signature

    ret = xrn_load_signature_sym( &signature, signature_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 486, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &monomial_key, monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 487, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial commitment

    ret = xrn_load_monomial_commitment( &monomial_commitment, monomial_commitment_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 488, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_response( &monomial_response, monomial_response_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 489, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 490, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 491, XERR_GENERAL_MSG );
        return ret;
    }

    // compute monomial proof

    ret =
        xrn_make_monomial_proof_from_signature( plain_text_fpr, xrn_matrix, signature, monomial_key,
                                                monomial_commitment, monomial_response, &monomial_proof,
                                                settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 492, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    // dump monomial proof

    ret = xrn_dump_monomial_proof( monomial_proof, monomial_proof_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 493, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_monomial_proof_from_signature( FILE * plain_text_fpr, xrn_matrix_t * xrn_matrix,
                                            xsignature_sym_t signature, xmonomial_key_t monomial_key,
                                            xmonomial_commitment_t monomial_commitment,
                                            xmonomial_response_t monomial_response,
                                            xmonomial_proof_t * monomial_proof,
                                            xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, carry, greater, ret, final_ret;
    xbinomial_commitment_t binomial_commitment;
    xnum_t distance_commitment_response, zero, proof_distance;
    xhash_t hash;
    xbinomial_key_t binomial_key;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( plain_text_fpr == NULL ) || ( xrn_matrix == NULL ) || ( monomial_proof == NULL ) ) {
        XPRINT_ERR( 494, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( binomial_commitment ); i++ ) {
        ( ( uint8_t * ) & binomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( binomial_key ); i++ ) {
        ( ( uint8_t * ) & binomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( hash ); i++ ) {
        ( ( uint8_t * ) & hash )[i] = 0;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    check_sparcity = 1;
    force_linearity = 1;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 495, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 496, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX )
         ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 497, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 498, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // compute hash
    ret = xrn_make_hash( plain_text_fpr, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 499, XERR_GENERAL_MSG );
        return ret;
    }

    binomial_key.start = hash.value;
    binomial_key.end = signature.proof;

    // calculate binomial commitment

    binomial_commitment.start = binomial_key.start;

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_commitment.start,
                             &monomial_commitment.distance, &binomial_commitment.end, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 500, XERR_GENERAL_MSG );
        return ret;
    }

    // modify monomial key

    ret =
        xrn_matrix_traverse( xrn_matrix, &signature.hint, &monomial_key.distance,
                             &monomial_key.distance, &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 501, XERR_GENERAL_MSG );
        return ret;
    }

    // calculate distance between monomial_response and monomial_commitment

    xrn_initialize_num( &zero );

    carry =
        xrn_add_nums( monomial_commitment.distance, monomial_response.distance, 0,
                      &distance_commitment_response );
    while ( carry == 1 ) {

        carry = xrn_add_nums( distance_commitment_response, zero, 1, &distance_commitment_response );

    }

    xrn_compare_greater_equal_nums( distance_commitment_response, monomial_key.distance, &greater );

    // invert distance

    if ( greater == 1 ) {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( distance_commitment_response, monomial_key.distance, &proof_distance );

    } else {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( monomial_key.distance, distance_commitment_response, &proof_distance );

    }

    monomial_proof->distance = proof_distance;

    return final_ret;

}

int xrn_make_monomial_proof_from_sym_certificate_wrapper( FILE * xrn_matrix_fpr, FILE * certificate_fpr,
                                                          FILE * monomial_key_fpr,
                                                          FILE * monomial_commitment_fpr,
                                                          FILE * monomial_response_fpr,
                                                          FILE * monomial_proof_fpw,
                                                          xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, final_ret, ret;
    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t monomial_key;
    xcertificate_sym_t certificate;
    xmonomial_commitment_t monomial_commitment;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;

    if ( ( certificate_fpr == NULL ) || ( xrn_matrix_fpr == NULL )
         || ( monomial_key_fpr == NULL )
         || ( monomial_commitment_fpr == NULL ) || ( monomial_response_fpr == NULL )
         || ( monomial_proof_fpw == NULL ) ) {
        XPRINT_ERR( 502, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( monomial_key ); i++ ) {
        ( ( uint8_t * ) & monomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( certificate ); i++ ) {
        ( ( uint8_t * ) & certificate )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_commitment ); i++ ) {
        ( ( uint8_t * ) & monomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_response ); i++ ) {
        ( ( uint8_t * ) & monomial_response )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_proof ); i++ ) {
        ( ( uint8_t * ) & monomial_proof )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 503, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load certificate

    ret = xrn_load_certificate_sym( &certificate, certificate_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 504, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &monomial_key, monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 505, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial commitment

    ret = xrn_load_monomial_commitment( &monomial_commitment, monomial_commitment_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 506, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_response( &monomial_response, monomial_response_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 507, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 508, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 509, XERR_GENERAL_MSG );
        return ret;
    }

    // compute monomial proof

    ret =
        xrn_make_monomial_proof_from_sym_certificate( xrn_matrix, certificate, monomial_key,
                                                      monomial_commitment, monomial_response, &monomial_proof,
                                                      settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 510, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    // dump monomial proof

    ret = xrn_dump_monomial_proof( monomial_proof, monomial_proof_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 511, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_monomial_proof_from_sym_certificate( xrn_matrix_t * xrn_matrix, xcertificate_sym_t certificate,
                                                  xmonomial_key_t monomial_key,
                                                  xmonomial_commitment_t monomial_commitment,
                                                  xmonomial_response_t monomial_response,
                                                  xmonomial_proof_t * monomial_proof,
                                                  xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, carry, greater, ret, final_ret;
    xbinomial_commitment_t binomial_commitment;
    xnum_t distance_commitment_response, zero, proof_distance;
    xhash_t hash;
    xbinomial_key_t binomial_key;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    struct certificate_t {
        xmonovalent_key_t monovalent_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( ( xrn_matrix == NULL ) || ( monomial_proof == NULL ) ) {
        XPRINT_ERR( 512, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( certificate.end_timestamp <= certificate.start_timestamp ) {
        XPRINT_ERR( 81, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( binomial_commitment ); i++ ) {
        ( ( uint8_t * ) & binomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( hash ); i++ ) {
        ( ( uint8_t * ) & hash )[i] = 0;
    }

    for ( i = 0; i < sizeof( binomial_key ); i++ ) {
        ( ( uint8_t * ) & binomial_key )[i] = 0;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 513, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 514, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 515, XERR_GENERAL_MSG );
            return ret;
        }

    }

    for ( i = 0; i < sizeof( certificate_tmp ); i++ ) {
        ( ( uint8_t * ) & certificate_tmp )[i] = 0;
    }

    certificate_tmp.monovalent_key = certificate.monovalent_key;
    certificate_tmp.start_timestamp = certificate.start_timestamp;
    certificate_tmp.end_timestamp = certificate.end_timestamp;
    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate.subject );

    // compute hash
    ret =
        xrn_make_hash_bytes( ( uint8_t * ) ( &certificate_tmp ), sizeof( certificate_tmp ), xrn_matrix, &hash,
                             settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 516, XERR_GENERAL_MSG );
        return ret;
    }

    binomial_key.start = hash.value;
    binomial_key.end = certificate.signature.proof;

    // calculate binomial commitment

    binomial_commitment.start = binomial_key.start;

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_commitment.start,
                             &monomial_commitment.distance, &binomial_commitment.end, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 517, XERR_GENERAL_MSG );
        return ret;
    }

    // modify monomial key

    ret =
        xrn_matrix_traverse( xrn_matrix, &certificate.signature.hint, &monomial_key.distance,
                             &monomial_key.distance, &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 518, XERR_GENERAL_MSG );
        return ret;
    }

    // calculate distance between monomial_response and monomial_commitment

    xrn_initialize_num( &zero );

    carry =
        xrn_add_nums( monomial_commitment.distance, monomial_response.distance, 0,
                      &distance_commitment_response );
    while ( carry == 1 ) {

        carry = xrn_add_nums( distance_commitment_response, zero, 1, &distance_commitment_response );

    }

    xrn_compare_greater_equal_nums( distance_commitment_response, monomial_key.distance, &greater );

    // invert distance

    if ( greater == 1 ) {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( distance_commitment_response, monomial_key.distance, &proof_distance );

    } else {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( monomial_key.distance, distance_commitment_response, &proof_distance );

    }

    monomial_proof->distance = proof_distance;

    return final_ret;

}

int xrn_make_monomial_proof_wrapper( FILE * binomial_key_fpr,
                                     FILE * xrn_matrix_fpr,
                                     FILE * monomial_key_fpr,
                                     FILE * monomial_commitment_fpr,
                                     FILE * monomial_response_fpr,
                                     FILE * monomial_proof_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, ret, final_ret;
    xrn_matrix_t *xrn_matrix;
    xbinomial_key_t binomial_key;
    xmonomial_key_t monomial_key;
    xmonomial_commitment_t monomial_commitment;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;

    if ( ( binomial_key_fpr == NULL ) || ( xrn_matrix_fpr == NULL ) || ( monomial_key_fpr == NULL )
         || ( monomial_commitment_fpr == NULL ) || ( monomial_response_fpr == NULL )
         || ( monomial_proof_fpw == NULL ) ) {
        XPRINT_ERR( 519, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    for ( i = 0; i < sizeof( binomial_key ); i++ ) {
        ( ( uint8_t * ) & binomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_key ); i++ ) {
        ( ( uint8_t * ) & monomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_commitment ); i++ ) {
        ( ( uint8_t * ) & monomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_response ); i++ ) {
        ( ( uint8_t * ) & monomial_response )[i] = 0;
    }

    for ( i = 0; i < sizeof( monomial_proof ); i++ ) {
        ( ( uint8_t * ) & monomial_proof )[i] = 0;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 520, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load binomial key

    ret = xrn_load_binomial_key( &binomial_key, binomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 521, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &monomial_key, monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 522, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial commitment

    ret = xrn_load_monomial_commitment( &monomial_commitment, monomial_commitment_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 523, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_response( &monomial_response, monomial_response_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 524, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 525, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 526, XERR_GENERAL_MSG );
        return ret;
    }

    // compute monomial proof

    ret =
        xrn_make_monomial_proof( xrn_matrix, binomial_key, monomial_key, monomial_commitment,
                                 monomial_response, &monomial_proof, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 527, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );

    // dump monomial proof

    ret = xrn_dump_monomial_proof( monomial_proof, monomial_proof_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 528, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_monomial_proof( xrn_matrix_t * xrn_matrix,
                             xbinomial_key_t binomial_key,
                             xmonomial_key_t monomial_key,
                             xmonomial_commitment_t monomial_commitment,
                             xmonomial_response_t monomial_response,
                             xmonomial_proof_t * monomial_proof, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, carry, greater, ret, final_ret;
    xbinomial_commitment_t binomial_commitment;
    xnum_t distance_commitment_response, zero, proof_distance;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( monomial_proof == NULL ) ) {
        XPRINT_ERR( 529, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( binomial_commitment ); i++ ) {
        ( ( uint8_t * ) & binomial_commitment )[i] = 0;
    }

    for ( i = 0; i < sizeof( proof_distance ); i++ ) {
        ( ( uint8_t * ) & proof_distance )[i] = 0;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 530, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 531, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 532, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // calculate binomial commitment

    binomial_commitment.start = binomial_key.start;
    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_commitment.start,
                             &monomial_commitment.distance, &binomial_commitment.end, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 533, XERR_GENERAL_MSG );
        return ret;
    }

    // calculate distance between monomial_response and monomial_commitment

    xrn_initialize_num( &zero );
    carry =
        xrn_add_nums( monomial_commitment.distance, monomial_response.distance, 0,
                      &distance_commitment_response );
    while ( carry == 1 ) {

        carry = xrn_add_nums( distance_commitment_response, zero, 1, &distance_commitment_response );

    }

    xrn_compare_greater_equal_nums( distance_commitment_response, monomial_key.distance, &greater );

    // invert distance

    if ( greater == 1 ) {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( distance_commitment_response, monomial_key.distance, &proof_distance );

    } else {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( monomial_key.distance, distance_commitment_response, &proof_distance );

    }

    monomial_proof->distance = proof_distance;

    return final_ret;

}

int xrn_check_monomial_proof_wrapper( FILE * binomial_key_fpr,
                                      FILE * xrn_matrix_fpr,
                                      FILE * binomial_commitment_fpr,
                                      FILE * monomial_response_fpr, FILE * monomial_proof_fpr,
                                      xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xbinomial_key_t binomial_key;
    xrn_matrix_t *xrn_matrix;
    xbinomial_commitment_t binomial_commitment;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;

    if ( ( binomial_key_fpr == NULL ) || ( xrn_matrix_fpr == NULL ) || ( binomial_commitment_fpr == NULL )
         || ( monomial_response_fpr == NULL ) || ( monomial_proof_fpr == NULL ) ) {
        XPRINT_ERR( 534, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // load binomial key

    ret = xrn_load_binomial_key( &binomial_key, binomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 535, XERR_GENERAL_MSG );
        return ret;
    }

    // load binomial commitment

    ret = xrn_load_binomial_commitment( &binomial_commitment, binomial_commitment_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 536, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_response( &monomial_response, monomial_response_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 537, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial proof

    ret = xrn_load_monomial_proof( &monomial_proof, monomial_proof_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 538, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 539, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 540, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_check_monomial_proof( binomial_key, xrn_matrix, binomial_commitment, monomial_response,
                                  monomial_proof, settings );

    XRN_FREE( xrn_matrix );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 541, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_check_monomial_proof( xbinomial_key_t binomial_key,
                              xrn_matrix_t * xrn_matrix,
                              xbinomial_commitment_t binomial_commitment,
                              xmonomial_response_t monomial_response, xmonomial_proof_t monomial_proof,
                              xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret, error, error0, error1;
    xnum_t proof_point_0, proof_point_1, binomial_key_end;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 542, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    constant_execution = 1;
    force_linearity = 1;
    check_sparcity = 1;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 543, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 544, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 545, XERR_GENERAL_MSG );
            return ret;
        }

    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_commitment.end, &monomial_response.distance,
                             &proof_point_0, &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 546, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_key.end, &monomial_proof.distance,
                             &proof_point_1, &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 547, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &proof_point_0, &monomial_proof.distance, &binomial_key_end,
                             &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 548, XERR_GENERAL_MSG );
        return ret;
    }

    XNUM_CMP( proof_point_0, proof_point_1, error0 );
    XNUM_CMP( binomial_key_end, binomial_key.end, error1 );
    error = error0 && error1;

    if ( error == 1 ) {
        ret = ( int ) XWAR_PROOF;
        XPRINT_NOT( 1 );
    } else {
        ret = XSUCCESS;
        XPRINT_NOT( 0 );
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    return final_ret;

}

int xrn_check_monomial_proof_from_signature_wrapper( FILE * plain_text_fpr,
                                                     FILE * xrn_matrix_fpr,
                                                     FILE * signature_fpr,
                                                     FILE * binomial_commitment_fpr,
                                                     FILE * monomial_response_fpr,
                                                     FILE * monomial_proof_fpr,
                                                     xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xrn_matrix_t *xrn_matrix;
    xsignature_sym_t signature_sym;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;
    xbinomial_commitment_t binomial_commitment;

    if ( ( plain_text_fpr == NULL ) || ( xrn_matrix_fpr == NULL ) || ( signature_fpr == NULL )
         || ( monomial_proof_fpr == NULL ) || ( monomial_response_fpr == NULL )
         || ( binomial_commitment_fpr == NULL ) ) {
        XPRINT_ERR( 565, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 566, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load binomial commitment

    ret = xrn_load_binomial_commitment( &binomial_commitment, binomial_commitment_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 567, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_response( &monomial_response, monomial_response_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 568, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_proof( &monomial_proof, monomial_proof_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 569, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 570, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 571, XERR_GENERAL_MSG );
        return ret;
    }

    // compute commitment

    ret = xrn_load_signature_sym( &signature_sym, signature_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 572, XERR_GENERAL_MSG );
        return ret;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 573, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret =
        xrn_check_monomial_proof_from_signature( plain_text_fpr, xrn_matrix, signature_sym,
                                                 binomial_commitment, monomial_response, monomial_proof,
                                                 settings );

    XRN_FREE( xrn_matrix );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 574, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_check_monomial_proof_from_signature( FILE * plain_text_fpr,
                                             xrn_matrix_t * xrn_matrix,
                                             xsignature_sym_t signature,
                                             xbinomial_commitment_t binomial_commitment,
                                             xmonomial_response_t monomial_response,
                                             xmonomial_proof_t monomial_proof,
                                             xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xhash_t hash;
    xbinomial_key_t binomial_key;
    xrn_log_t xlog2;

    if ( ( plain_text_fpr == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 575, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 576, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 577, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 578, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // compute hash
    ret = xrn_make_hash( plain_text_fpr, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 579, XERR_GENERAL_MSG );
        return ret;
    }

    binomial_key.start = hash.value;
    binomial_key.end = signature.proof;

    ret =
        xrn_check_monomial_proof( binomial_key, xrn_matrix, binomial_commitment, monomial_response,
                                  monomial_proof, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 580, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_check_monomial_proof_from_certificate_wrapper( FILE * certificate_fpr,
                                                       FILE * xrn_matrix_fpr,
                                                       FILE * binomial_commitment_fpr,
                                                       FILE * monomial_response_fpr,
                                                       FILE * monomial_proof_fpr,
                                                       xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xrn_matrix_t *xrn_matrix;
    xcertificate_sym_t certificate_sym;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;
    xbinomial_commitment_t binomial_commitment;

    if ( ( xrn_matrix_fpr == NULL ) || ( certificate_fpr == NULL ) || ( monomial_response_fpr == NULL )
         || ( monomial_proof_fpr == NULL ) || ( binomial_commitment_fpr == NULL ) ) {
        XPRINT_ERR( 581, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 582, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load binomial commitment

    ret = xrn_load_binomial_commitment( &binomial_commitment, binomial_commitment_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 583, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial response

    ret = xrn_load_monomial_response( &monomial_response, monomial_response_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 584, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial proof

    ret = xrn_load_monomial_proof( &monomial_proof, monomial_proof_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 585, XERR_GENERAL_MSG );
        return ret;
    }

    // load matrix        

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 586, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 587, XERR_GENERAL_MSG );
        return ret;
    }

    // compute commitment

    ret = xrn_load_certificate_sym( &certificate_sym, certificate_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 588, XERR_GENERAL_MSG );
        return ret;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 589, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret =
        xrn_check_monomial_proof_from_certificate( certificate_sym, xrn_matrix, binomial_commitment,
                                                   monomial_response, monomial_proof, settings );

    XRN_FREE( xrn_matrix );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 590, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_check_monomial_proof_from_certificate( xcertificate_sym_t certificate,
                                               xrn_matrix_t * xrn_matrix,
                                               xbinomial_commitment_t binomial_commitment,
                                               xmonomial_response_t monomial_response,
                                               xmonomial_proof_t monomial_proof,
                                               xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret, i;
    xhash_t hash;
    xbinomial_key_t binomial_key;
    xrn_log_t xlog2;

    struct certificate_t {
        xmonovalent_key_t monovalent_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 591, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( certificate.end_timestamp <= certificate.start_timestamp ) {
        XPRINT_ERR( 84, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 592, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 593, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 594, XERR_GENERAL_MSG );
            return ret;
        }

    }

    for ( i = 0; i < sizeof( certificate_tmp ); i++ ) {
        ( ( uint8_t * ) & certificate_tmp )[i] = 0;
    }

    certificate_tmp.monovalent_key = certificate.monovalent_key;
    certificate_tmp.start_timestamp = certificate.start_timestamp;
    certificate_tmp.end_timestamp = certificate.end_timestamp;
    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate.subject );

    // compute hash
    ret =
        xrn_make_hash_bytes( ( uint8_t * ) ( &certificate_tmp ), sizeof( certificate_tmp ), xrn_matrix, &hash,
                             settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 595, XERR_GENERAL_MSG );
        return ret;
    }

    binomial_key.start = hash.value;
    binomial_key.end = certificate.signature.proof;

    ret =
        xrn_check_monomial_proof( binomial_key, xrn_matrix, binomial_commitment, monomial_response,
                                  monomial_proof, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 596, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_split_wrapper( FILE * input_file_fpr,
                       FILE * output_file_challenge_fpw,
                       FILE * output_file_solution_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;

    if ( ( input_file_fpr == NULL ) || ( output_file_challenge_fpw == NULL )
         || ( output_file_solution_fpw == NULL ) ) {
        XPRINT_ERR( 737, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 738, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    final_ret = XSUCCESS;

    ret = xrn_split_stream( input_file_fpr, output_file_challenge_fpw, output_file_solution_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 741, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_split_stream( FILE * input_file_fpr,
                      FILE * output_file_challenge_fpw,
                      FILE * output_file_solution_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t id;
    int final_ret, ret;
    xrn_encoding_param_t enc_param_challenge, enc_param_solution;
    xrn_lib_xtype_t type;

    xrn_crypto_lib_header_t header_solution;
    xrn_crypto_lib_header_t header_challenge;

    if ( ( input_file_fpr == NULL ) || ( output_file_challenge_fpw == NULL )
         || ( output_file_solution_fpw == NULL ) ) {
        XPRINT_ERR( 763, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 803, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( settings.state_size <= 2 ) {
        XPRINT_ERR( 769, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize encoding decoding param

    ret = xrn_initialize_encoding_parameters( &enc_param_solution, settings.encoding_settings.o_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 146, XERR_GENERAL_MSG );
        return ret;
    }

    // dump solution header

    type = c_solution;
    ret = xrn_initialize_header( type,
                                 settings.crc_bytes,
                                 settings.state_size, settings.component_id, &header_solution );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 153, XERR_GENERAL_MSG );
        return ret;
    }

    // using encoding_guard as password for enc_param_challenge

    ret = xrn_permute_encoding_param_with_pass( enc_param_solution, header_solution.encoding_guard,
                                                sizeof( header_solution.encoding_guard ),
                                                &enc_param_challenge );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 154, XERR_GENERAL_MSG );
        return ret;
    }

    // encoding header solution

    if ( 1 !=
         xrn_fwrite_encoder( &header_solution, sizeof( header_solution ), 1,
                             output_file_solution_fpw, &enc_param_solution ) ) {
        XPRINT_ERR( 598, XERR_IO_MSG );
        return XERR_IO;
    }

    // dump challenge header

    type = c_challenge;

    ret = xrn_initialize_header( type,
                                 settings.crc_bytes,
                                 settings.state_size, settings.component_id, &header_challenge );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1, XERR_GENERAL_MSG );
        return ret;
    }

    if ( 1 !=
         xrn_fwrite_encoder( &header_challenge, sizeof( header_challenge ), 1,
                             output_file_challenge_fpw, &enc_param_challenge ) ) {
        XPRINT_ERR( 206, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( XSUCCESS != get_random_bytes( ( uint8_t * ) & id, sizeof( id ) ) ) {
        XPRINT_ERR( 775, XERR_IO_MSG );
        return XERR_IO;
    }

    // write id 

    if ( 1 !=
         xrn_fwrite_encoder( &id, sizeof( uint64_t ), 1, output_file_challenge_fpw, &enc_param_challenge ) ) {
        XPRINT_ERR( 776, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fwrite_encoder( &id, sizeof( uint64_t ), 1, output_file_solution_fpw, &enc_param_solution ) ) {
        XPRINT_ERR( 777, XERR_IO_MSG );
        return XERR_IO;
    }

    ret =
        loop_split_stream( input_file_fpr, output_file_challenge_fpw, output_file_solution_fpw,
                           enc_param_challenge, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 778, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_join_wrapper( FILE * input_file_challenge_fpr,
                      FILE * input_file_solution_fpr,
                      FILE * output_file_join_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;

    if ( ( input_file_challenge_fpr == NULL ) || ( input_file_solution_fpr == NULL )
         || ( output_file_join_fpw == NULL ) ) {
        XPRINT_ERR( 814, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 815, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret =
        xrn_join_stream( input_file_challenge_fpr, input_file_solution_fpr, output_file_join_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 818, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_join_stream( FILE * input_file_challenge_fpr,
                     FILE * input_file_solution_fpr,
                     FILE * output_file_join_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t id0, id1;
    int ret;
    int final_ret;
    xrn_encoding_param_t enc_param_tmp, enc_param_challenge;
    xrn_encoding_param_t enc_param_solution;
    xrn_lib_xtype_t exp_type;
    uint8_t state_size_challenge;
    xrn_lib_xtype_t type_solution;
    uint8_t crc_bytes_solution;
    uint8_t state_size_solution;
    uint32_t reserved_0, reserved_1;
    uint8_t crc_bytes_challenge;
    xrn_lib_xtype_t type_challenge;
    uint32_t reserved_0_challenge, reserved_1_challenge;
    uint8_t encoding_guard_tmp[256];
    xrn_crypto_lib_header_t header_local;

    if ( ( input_file_challenge_fpr == NULL ) || ( input_file_solution_fpr == NULL )
         || ( output_file_join_fpw == NULL ) ) {
        XPRINT_ERR( 819, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // load challenge encoding paramethers

    // initialize encoding decoding param
    ret = xrn_initialize_encoding_parameters( &enc_param_solution, settings.encoding_settings.i_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 242, XERR_GENERAL_MSG );
        return ret;
    }

    enc_param_tmp = enc_param_solution;

    ret =
        xrn_fread_decoder( &encoding_guard_tmp, sizeof( encoding_guard_tmp ), 1, input_file_solution_fpr,
                           &enc_param_tmp );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 248, XERR_VERSION_MSG );
        return XERR_VERSION;
    }

    ret = xrn_permute_encoding_param_with_pass( enc_param_solution, encoding_guard_tmp,
                                                sizeof( encoding_guard_tmp ), &enc_param_challenge );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 621, XERR_VERSION_MSG );
        return XERR_VERSION;
    }

    rewind( input_file_solution_fpr );

    // load header

    exp_type = c_solution;
    ret =
        xrn_load_header_file( input_file_solution_fpr, &crc_bytes_solution,
                              &type_solution, exp_type,
                              &state_size_solution, &reserved_0, &reserved_1, &enc_param_solution, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1075, XERR_GENERAL_MSG );
        return ret;
    }

    // load challenge header

    if ( xrn_fread_decoder
         ( &header_local, sizeof( header_local ), 1, input_file_challenge_fpr, &enc_param_challenge ) != 1 ) {
        XPRINT_ERR( 3, XERR_IO_MSG );
        return XERR_IO;
    }

    exp_type = c_challenge;
    ret =
        xrn_load_header( header_local,
                         &crc_bytes_challenge, &type_challenge, exp_type, &state_size_challenge,
                         &reserved_0_challenge, &reserved_1_challenge );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 105, XERR_GENERAL_MSG );
        return ret;
    }

    if ( ( crc_bytes_challenge != crc_bytes_solution ) || ( state_size_challenge != state_size_solution )
         || ( reserved_0_challenge != reserved_0 ) || ( reserved_1_challenge != reserved_1 ) ) {
        XPRINT_ERR( 106, XERR_IO_MSG );
        return XERR_IO;
    }

    settings.crc_bytes = crc_bytes_challenge;
    settings.state_size = state_size_challenge;

    id0 = 0;
    id1 = 0;

    if ( xrn_fread_decoder( &id0, sizeof( uint64_t ), 1, input_file_challenge_fpr, &enc_param_challenge ) !=
         1 ) {
        XPRINT_ERR( 834, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( xrn_fread_decoder( &id1, sizeof( uint64_t ), 1, input_file_solution_fpr, &enc_param_solution ) != 1 ) {
        XPRINT_ERR( 835, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( id0 != id1 ) {
        XPRINT_ERR( 836, XERR_JOIN_MSG );
        return XERR_JOIN;
    }

    if ( settings.state_size <= 2 ) {
        XPRINT_ERR( 837, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret =
        loop_join_stream( input_file_challenge_fpr, input_file_solution_fpr, output_file_join_fpw,
                          enc_param_challenge, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 838, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_exchange_monomial_key_wrapper( FILE * xrn_matrix_fp,
                                       FILE * internal_binomial_key_fp,
                                       FILE * external_binomial_key_fp, FILE * monomial_key_fp,
                                       FILE * shared_key_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xrn_matrix_t *xrn_matrix;
    xbinomial_key_t internal_binomial_key;
    xbinomial_key_t external_binomial_key;
    xmonomial_key_t monomial_key;
    xmonomial_key_t shared_key;

    if ( ( xrn_matrix_fp == NULL ) || ( internal_binomial_key_fp == NULL ) || ( monomial_key_fp == NULL )
         || ( shared_key_fp == NULL )
         || ( external_binomial_key_fp == NULL )
         ) {
        XPRINT_ERR( 839, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 840, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize variables

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 841, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load binomial keys

    ret = xrn_load_binomial_key( &internal_binomial_key, internal_binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 842, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_binomial_key( &external_binomial_key, external_binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 843, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &monomial_key, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 844, XERR_GENERAL_MSG );
        return ret;
    }

    // load xoron matrix

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 845, XERR_GENERAL_MSG );
        return ret;
    }

    // key exchange

    ret =
        xrn_exchange_monomial_key( xrn_matrix, internal_binomial_key, external_binomial_key, monomial_key,
                                   &shared_key, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 846, XERR_GENERAL_MSG );
        return ret;
    }

    // storing the key

    ret = xrn_dump_monomial_key( shared_key, shared_key_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 847, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_exchange_monomial_key( xrn_matrix_t * xrn_matrix,
                               xbinomial_key_t internal_binomial_key,
                               xbinomial_key_t external_binomial_key,
                               xmonomial_key_t monomial_key, xmonomial_key_t * shared_key,
                               xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int error, ret, final_ret;
    xnum_t key1;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( shared_key == NULL ) ) {
        XPRINT_ERR( 848, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 849, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    final_ret = XSUCCESS;
    constant_execution = 1;
    force_linearity = 1;
    check_sparcity = 1;

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 850, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check non linearity

    ret = non_linear_start_check( internal_binomial_key.start, xrn_matrix );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 831, XERR_GENERAL_MSG );
        return ret;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 851, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // check that the starting points are the same
    XNUM_CMP( external_binomial_key.start, internal_binomial_key.start, error );

    if ( error != 0 ) {
        XPRINT_ERR( 852, XERR_STARTS_MSG );
        return XERR_STARTS;
    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &external_binomial_key.end, &monomial_key.distance,
                             &key1, &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 853, XERR_GENERAL_MSG );
        return ret;
    }

    force_linearity = 0;
    xrn_matrix_traverse( xrn_matrix, &external_binomial_key.start, &key1, &key1, &constant_execution,
                         &force_linearity, &check_sparcity );

    shared_key->distance = key1;

    return final_ret;

}

int xrn_check_signature_asymmetric( FILE * input_fp,
                                    xbinomial_key_t binomial_key,
                                    xrn_matrix_t * xrn_matrix, xsignature_asy_t signature,
                                    xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int error0, error1;
    int ret;
    xnum_t tmp, sig_ver0, sig_ver1;
    xhash_t hash;
    int final_ret;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( input_fp == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 869, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 870, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 871, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 872, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = xrn_make_hash( input_fp, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 873, XERR_GENERAL_MSG );
        return ret;
    }

    // verify signature

    ret =
        xrn_matrix_traverse( xrn_matrix, &signature.hint, &hash.value, &tmp, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 874, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &tmp, &signature.proof, &sig_ver0, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 875, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_key.end, &signature.proof, &sig_ver1,
                             &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 876, XERR_GENERAL_MSG );
        return ret;
    }

    XNUM_CMP( sig_ver0, binomial_key.end, error0 );
    XNUM_CMP( sig_ver1, tmp, error1 );

    if ( ( error1 != 0 ) && ( error0 != 0 ) ) {

        XPRINT_NOT( 1 );
        ret = ( int ) XWAR_SIG;
    } else {
        XPRINT_NOT( 0 );
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    return final_ret;

}

int xrn_check_signature_asymmetric_wrapper( FILE * input_fp,
                                            FILE * binomial_key_fp,
                                            FILE * xrn_matrix_fp,
                                            FILE * signature_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xbinomial_key_t bkey;
    xsignature_asy_t sig;
    int ret;
    int final_ret;

    if ( ( input_fp == NULL ) || ( binomial_key_fp == NULL ) || ( xrn_matrix_fp == NULL )
         || ( signature_fp == NULL ) ) {
        XPRINT_ERR( 877, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 878, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // read signature
    ret = xrn_load_signature_asy( &sig, signature_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 879, XERR_GENERAL_MSG );
        return ret;
    }

    // initialize variables

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 880, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load binomial key

    ret = xrn_load_binomial_key( &bkey, binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 881, XERR_GENERAL_MSG );
        return ret;
    }

    // load xoron matrix

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 882, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_signature_asymmetric( input_fp, bkey, xrn_matrix, sig, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 883, XERR_GENERAL_MSG );
        return ret;
    }

    // free memory

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_make_signature_asymmetric( FILE * input_fp, xmonomial_key_t monomial_key,
                                   xbinomial_key_t binomial_key, xrn_matrix_t * xrn_matrix,
                                   xsignature_asy_t * signature, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xnum_t sum, xnum_rnd, hint, zero, proof;
    xhash_t hash;
    int final_ret, ret, carry, greater;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( input_fp == NULL ) || ( xrn_matrix == NULL ) || ( signature == NULL ) ) {
        XPRINT_ERR( 900, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 901, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 902, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 903, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // compute hash

    ret = xrn_make_hash( input_fp, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 904, XERR_GENERAL_MSG );
        return ret;
    }

    // compute hint

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &xnum_rnd );
    if ( XSUCCESS != ret ) {
        XPRINT_ERR( 905, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_key.start, &xnum_rnd, &hint, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 906, XERR_GENERAL_MSG );
        return ret;
    }

    // calculate distance between monomial_response and monomial_commitment

    xrn_initialize_num( &zero );
    carry = xrn_add_nums( xnum_rnd, hash.value, 0, &sum );

    while ( carry == 1 ) {

        carry = xrn_add_nums( sum, zero, 1, &sum );

    }

    xrn_compare_greater_equal_nums( sum, monomial_key.distance, &greater );

    // invert distance

    if ( greater == 1 ) {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( sum, monomial_key.distance, &proof );

    } else {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( monomial_key.distance, sum, &proof );

    }

    signature->hint = hint;
    signature->proof = proof;

    return final_ret;

}

int xrn_make_signature_asymmetric_wrapper( FILE * input_fp,
                                           FILE * monomial_key_fp,
                                           FILE * binomial_key_fp,
                                           FILE * xrn_matrix_fp,
                                           FILE * signature_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t mk;
    xbinomial_key_t bk;
    xsignature_asy_t sig;
    int final_ret, ret;

    if ( ( input_fp == NULL ) || ( monomial_key_fp == NULL ) || ( binomial_key_fp == NULL )
         || ( xrn_matrix_fp == NULL )
         || ( signature_fp == NULL ) ) {
        XPRINT_ERR( 907, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 908, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize variables

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 909, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load xoron matrix
    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 910, XERR_GENERAL_MSG );
        return ret;
    }

    // load binomial key

    ret = xrn_load_binomial_key( &bk, binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 911, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &mk, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 912, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_make_signature_asymmetric( input_fp, mk, bk, xrn_matrix, &sig, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 913, XERR_GENERAL_MSG );
        return ret;
    }

    // dump signature

    ret = xrn_dump_signature_asy( sig, signature_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 914, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_make_signature_symmetric( FILE * input_fp,
                                  xmonomial_key_t monomial_key,
                                  xrn_matrix_t * xrn_matrix, xsignature_sym_t * signature,
                                  xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );
    xhash_t hash;
    xnum_t rnd, proof, tmp, hint;
    int final_ret, ret;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( input_fp == NULL ) || ( xrn_matrix == NULL ) || ( signature == NULL ) ) {
        XPRINT_ERR( 929, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 930, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 931, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 932, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 933, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // compute hash

    ret = xrn_make_hash( input_fp, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 934, XERR_GENERAL_MSG );
        return ret;
    }

    // compute random number

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &rnd );
    if ( XSUCCESS != ret ) {
        XPRINT_ERR( 935, XERR_GENERAL_MSG );
        return ret;
    }

    hint = rnd;

    // compute a secret distance

    constant_execution = settings.const_exec_time;
    force_linearity = 0;
    check_sparcity = 1;
    xrn_matrix_traverse( xrn_matrix, &hint, &monomial_key.distance, &tmp, &constant_execution,
                         &force_linearity, &check_sparcity );

    // compute the proof

    xrn_matrix_traverse( xrn_matrix, &hash.value, &tmp, &proof, &constant_execution, &force_linearity,
                         &check_sparcity );

    // store the results

    signature->hint = hint;
    signature->proof = proof;

    return final_ret;
}

int xrn_make_signature_symmetric_wrapper( FILE * input_fp,
                                          FILE * monomial_key_fp,
                                          FILE * xrn_matrix_fp,
                                          FILE * signature_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t mkey;
    xsignature_sym_t sig;
    int final_ret, ret;

    if ( ( input_fp == NULL ) || ( monomial_key_fp == NULL ) || ( xrn_matrix_fp == NULL )
         || ( signature_fp == NULL ) ) {
        XPRINT_ERR( 936, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 937, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // initialize variables

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 938, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load xoron matrix

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 939, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 940, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_make_signature_symmetric( input_fp, mkey, xrn_matrix, &sig, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 941, XERR_GENERAL_MSG );
        return ret;
    }

    // write signature

    ret = xrn_dump_signature_sym( sig, signature_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 942, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_check_signature_symmetric( FILE * input_fp,
                                   xmonomial_key_t monomial_key,
                                   xrn_matrix_t * xrn_matrix, xsignature_sym_t signature,
                                   xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int error;
    xnum_t sig_comp, tmp;
    xhash_t hash;
    int final_ret, ret;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( input_fp == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 949, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 950, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 951, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 952, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 953, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // compute hash
    ret = xrn_make_hash( input_fp, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 954, XERR_GENERAL_MSG );
        return ret;
    }

    // calculate distance between hash and proof

    constant_execution = settings.const_exec_time;
    force_linearity = 0;
    check_sparcity = 1;
    xrn_matrix_traverse( xrn_matrix, &signature.hint, &monomial_key.distance, &tmp, &constant_execution,
                         &force_linearity, &check_sparcity );

    // compute temporary number

    xrn_matrix_traverse( xrn_matrix, &hash.value, &tmp, &sig_comp, &constant_execution,
                         &force_linearity, &check_sparcity );

    XNUM_CMP( signature.proof, sig_comp, error );

    if ( error != 0 ) {
        XPRINT_NOT( 1 );
        ret = ( int ) XWAR_SIG;
    } else {
        XPRINT_NOT( 0 );
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    return final_ret;

}

int xrn_check_signature_symmetric_wrapper( FILE * input_fp,
                                           FILE * monomial_key_fp,
                                           FILE * xrn_matrix_fp,
                                           FILE * signature_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t mkey;
    xsignature_sym_t sig;
    int final_ret, ret;

    if ( ( input_fp == NULL ) || ( monomial_key_fp == NULL ) || ( xrn_matrix_fp == NULL )
         || ( signature_fp == NULL ) ) {
        XPRINT_ERR( 962, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 963, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // read signature

    ret = xrn_load_signature_sym( &sig, signature_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 964, XERR_GENERAL_MSG );
        return ret;
    }

    // initialize variables

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 965, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load xoron matrix

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 966, XERR_GENERAL_MSG );
        return ret;
    }

    // load monomial key

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 967, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_signature_symmetric( input_fp, mkey, xrn_matrix, sig, settings );

    XRN_FREE( xrn_matrix );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 968, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_generate_confidential_pseudo_random_number_wrapper( FILE * point_fpr,
                                                            FILE * monomial_key_fpr,
                                                            FILE * xrn_matrix_fpr, FILE * point_fpw,
                                                            xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_key_t monomial_key;
    xrn_point_t point_start;
    xrn_point_t point_end;
    int final_ret, ret;

    xrn_matrix_t *xrn_matrix;

    if ( ( point_fpr == NULL ) || ( monomial_key_fpr == NULL ) || ( xrn_matrix_fpr == NULL )
         || ( point_fpw == NULL ) ) {
        XPRINT_ERR( 969, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 970, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = xrn_load_monomial_key( &monomial_key, monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 971, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_point( &point_start, point_fpr, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 972, XERR_GENERAL_MSG );
        return ret;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 973, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // load xoron matrix

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 974, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_generate_confidential_pseudo_random_number( point_start, monomial_key, xrn_matrix, &point_end,
                                                        settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 975, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_point( point_end, point_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 976, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_generate_confidential_pseudo_random_number( xrn_point_t point_start, xmonomial_key_t monomial_key,
                                                    xrn_matrix_t * xrn_matrix, xrn_point_t * point_end,
                                                    xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t i;
    xstate_t state;
    xstate_t state_o;
    uint64_t state_size;
    int final_ret, ret;
    xrn_log_t xlog2;

    if ( ( point_end == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 977, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 978, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 979, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 980, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 981, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    state_size = ( uint64_t ) settings.state_size + 1;

    state.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( state.xnums == NULL ) {
        XPRINT_ERR( 982, XERR_NULL_MSG );
        return XERR_NULL;
    }

    state_o.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( state_o.xnums == NULL ) {
        XRN_FREE_XSTATE( state.xnums, settings.state_size );
        XPRINT_ERR( 983, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // Initialize variables

    for ( i = 0; i < state_size; i++ ) {
        xrn_initialize_num( &state_o.xnums[i] );
    }

    // generate a random state

    ret = expand_xnum( xrn_matrix, monomial_key.distance, &state, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( state.xnums, settings.state_size );
        XRN_FREE_XSTATE( state_o.xnums, settings.state_size );
        XPRINT_ERR( 66, XERR_GENERAL_MSG );
        return ret;
    }

    // generate a random state

    ret = expand_xnum( xrn_matrix, point_start.point, &state_o, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( state.xnums, settings.state_size );
        XRN_FREE_XSTATE( state_o.xnums, settings.state_size );
        XPRINT_ERR( 67, XERR_GENERAL_MSG );
        return ret;
    }

    // Update internal state

    for ( i = 0; i < state_size; i++ ) {
        X_XOR3( state.xnums[i], state_o.xnums[i], state_o.xnums[i] );
    }

    // Perform cross traverses on the input

    ret = xrn_cross_traverses( &state_o, xrn_matrix, &state_o, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( state.xnums, settings.state_size );
        XRN_FREE_XSTATE( state_o.xnums, settings.state_size );
        XPRINT_ERR( 984, XERR_GENERAL_MSG );
        return ret;
    }

    xrn_compress_state( state_o, &point_end->point, settings );

    XRN_FREE_XSTATE( state.xnums, settings.state_size );
    XRN_FREE_XSTATE( state_o.xnums, settings.state_size );
    return final_ret;

}

int xrn_make_hash( FILE * fpi, xrn_matrix_t * xrn_matrix, xhash_t * hash, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t block_i, i;
    xstate_t state_tmp;
    xstate_t state_internal;
    hash_load_variables_t load_variables;
    xnum_t init_vector;
    uint64_t state_size;
    int final_ret, ret;
    xrn_encoding_param_t enc_param;
    xrn_log_t xlog2;

    if ( ( hash == NULL ) || ( fpi == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1001, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // initialize encoding decoding param

    ret = xrn_initialize_encoding_parameters( &enc_param, settings.encoding_settings.o_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1002, XERR_GENERAL_MSG );
        return ret;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1003, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1004, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1005, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    state_size = ( uint64_t ) settings.state_size + 1;
    state_tmp.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( state_tmp.xnums == NULL ) {
        XPRINT_ERR( 1006, XERR_NULL_MSG );
        return XERR_NULL;
    }

    state_internal.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( state_internal.xnums == NULL ) {
        XRN_FREE_XSTATE( state_tmp.xnums, settings.state_size );
        XPRINT_ERR( 1007, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // Initialize variables

    for ( i = 0; i < sizeof( xnum_t ) - sizeof( uint64_t ); i++ ) {
        ( ( uint8_t * ) & init_vector )[i] = 0;
    }

    for ( i = 0; i < state_size; i++ ) {
        xrn_initialize_num( &state_internal.xnums[i] );
    }

    crypto_hash_init( &load_variables );

    // Perform hashing

    for ( block_i = 0; !load_variables.last_block; block_i++ ) {

        // generate a random state

        init_round_state( xrn_matrix, init_vector, block_i, &state_tmp, settings );

        // Update internal state

        for ( i = 0; i < state_size; i++ ) {
            X_XOR3( state_tmp.xnums[i], state_internal.xnums[i], state_internal.xnums[i] );
        }

        // Read the file
        ret = plain_text_2_hash_block( fpi, ( int ) block_i, &state_tmp, &load_variables, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XRN_FREE_XSTATE( state_tmp.xnums, settings.state_size );
            XRN_FREE_XSTATE( state_internal.xnums, settings.state_size );
            XPRINT_ERR( 1008, XERR_GENERAL_MSG );
            return ret;
        }

        // Perform cross traverses on the input

        ret = xrn_cross_traverses( &state_tmp, xrn_matrix, &state_tmp, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XRN_FREE_XSTATE( state_tmp.xnums, settings.state_size );
            XRN_FREE_XSTATE( state_internal.xnums, settings.state_size );
            XPRINT_ERR( 1010, XERR_GENERAL_MSG );
            return ret;
        }

        // Mix with the internal state

        for ( i = 0; i < state_size; i++ ) {
            X_XOR3( state_tmp.xnums[i], state_internal.xnums[i], state_internal.xnums[i] );
        }

    }

    xrn_compress_state( state_internal, &hash->value, settings );

    XRN_FREE_XSTATE( state_tmp.xnums, settings.state_size );
    XRN_FREE_XSTATE( state_internal.xnums, settings.state_size );

    return final_ret;

}

int xrn_make_hash_wrapper( FILE * fpi, FILE * xrn_matrix_fp, FILE * hash_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xhash_t hash;
    int final_ret, ret;

    if ( ( hash_fp == NULL ) || ( fpi == NULL ) || ( xrn_matrix_fp == NULL ) ) {
        XPRINT_ERR( 1011, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1012, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1013, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1014, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_make_hash( fpi, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1015, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_hash( hash, hash_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1016, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_check_hash_wrapper( FILE * input_file_fpr, FILE * input_hash_fpr, FILE * xrn_matrix_fpr,
                            xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );
    int final_ret, ret;
    xhash_t hash;
    xrn_matrix_t *xrn_matrix;

    if ( ( input_file_fpr == NULL ) || ( input_hash_fpr == NULL ) || ( xrn_matrix_fpr == NULL ) ) {
        XPRINT_ERR( 1017, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1018, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1020, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1021, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_hash( &hash, input_hash_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1019, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_hash( input_file_fpr, hash, xrn_matrix, settings );

    XRN_FREE( xrn_matrix );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1022, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_check_hash( FILE * input_file_fpr, xhash_t hash, xrn_matrix_t * xrn_matrix,
                    xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    int equal;
    xhash_t hash2;
    xrn_log_t xlog2;

    if ( ( input_file_fpr == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1023, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1024, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1025, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1026, XERR_GENERAL_MSG );
            return ret;
        }

    }

    ret = xrn_make_hash( input_file_fpr, xrn_matrix, &hash2, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1027, XERR_GENERAL_MSG );
        return ret;
    }

    XNUM_CMP( hash.value, hash2.value, equal );

    if ( equal == 0 ) {
        XPRINT_NOT( 0 );
        ret = XEQUAL;
    } else {
        XPRINT_NOT( 1 );
        ret = XNOT_EQUAL;
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    return final_ret;

}

int xrn_decrypt_asymmetric( FILE * fpi,
                            xrn_matrix_t * xrn_matrix,
                            xmonomial_key_t monomial_key, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_key_t shared;
    xnum_t hint;
    xnum_t init_vector;
    xstate_t hidden_state;
    uint64_t state_size;
    int ret;
    int final_ret;
    xrn_encoding_param_t enc_param;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;
    xrn_log_t xlog2;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1067, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1068, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1069, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1070, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load header

    exp_type = c_asy_encryption;
    ret =
        xrn_load_header_file( fpi, &crc_bytes_header, &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 773, XERR_GENERAL_MSG );
        return ret;
    }

    settings.crc_bytes = crc_bytes_header;
    settings.state_size = state_size_header;

    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1078, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // read initialization vector 

    if ( xrn_fread_decoder( &init_vector, sizeof( xnum_t ) - sizeof( uint64_t ), 1, fpi, &enc_param ) != 1 ) {
        XPRINT_ERR( 1079, XERR_IO_MSG );
        return XERR_IO;
    }

    // Read hint

    if ( xrn_fread_decoder( &hint, sizeof( xnum_t ), 1, fpi, &enc_param ) != 1 ) {
        XPRINT_ERR( 1080, XERR_IO_MSG );
        return XERR_IO;
    }

    // Compute shared key

    ret =
        xrn_matrix_traverse( xrn_matrix, &hint, &monomial_key.distance, &shared.distance,
                             &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1081, XERR_GENERAL_MSG );
        return ret;
    }

    force_linearity = 0;
    xrn_matrix_traverse( xrn_matrix, &hint, &shared.distance, &shared.distance, &constant_execution,
                         &force_linearity, &check_sparcity );
    force_linearity = 1;

    state_size = ( uint64_t ) settings.state_size + 1;
    hidden_state.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( NULL == hidden_state.xnums ) {
        XPRINT_ERR( 1082, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = expand_xnum( xrn_matrix, shared.distance, &hidden_state, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1083, XERR_GENERAL_MSG );
        return ret;
    }

    ret = loop_dec_stream( fpi, fpo, &hidden_state, xrn_matrix, init_vector, enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1084, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );

    return final_ret;

}

int xrn_decrypt_asymmetric_wrapper( FILE * fpi,
                                    FILE * xrn_matrix_fp,
                                    FILE * monomial_key_fp, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t mkey;
    int final_ret, ret;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( monomial_key_fp == NULL )
         || ( xrn_matrix_fp == NULL ) ) {
        XPRINT_ERR( 1085, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1086, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1087, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1088, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1089, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_decrypt_asymmetric( fpi, xrn_matrix, mkey, fpo, settings );

    XRN_FREE( xrn_matrix );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1090, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_encrypt_asymmetric( FILE * fpi,
                            xrn_matrix_t * xrn_matrix,
                            xbinomial_key_t binomial_key, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_lib_xtype_t type;
    xmonomial_key_t shared;
    xnum_t hint, xnum_rnd;
    xnum_t init_vector;
    xstate_t hidden_state;
    uint64_t state_size;
    int final_ret, ret;
    xrn_encoding_param_t enc_param;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1118, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1119, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1120, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1121, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // dump headers

    type = c_asy_encryption;
    ret = xrn_dump_header_file( fpo, type, settings.crc_bytes, settings.state_size, &enc_param, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 772, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // Write initialization vector 

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &init_vector );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1126, XERR_GENERAL_MSG );
        return ret;
    }

    if ( 1 != xrn_fwrite_encoder( &init_vector, sizeof( xnum_t ) - sizeof( uint64_t ), 1, fpo, &enc_param ) ) {
        XPRINT_ERR( 1127, XERR_IO_MSG );
        return XERR_IO;
    }

    // Compute hint

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &xnum_rnd );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1128, XERR_GENERAL_MSG );
        return ret;
    }

    force_linearity = 0;
    xrn_matrix_traverse( xrn_matrix, &binomial_key.start, &xnum_rnd, &hint, &constant_execution,
                         &force_linearity, &check_sparcity );
    force_linearity = 1;

    // Write hint

    if ( 1 != xrn_fwrite_encoder( &hint, sizeof( xnum_t ), 1, fpo, &enc_param ) ) {
        XPRINT_ERR( 1129, XERR_IO_MSG );
        return XERR_IO;
    }

    // Compute shared key

    ret =
        xrn_matrix_traverse( xrn_matrix, &binomial_key.end, &xnum_rnd, &shared.distance,
                             &constant_execution, &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1130, XERR_GENERAL_MSG );
        return ret;
    }

    force_linearity = 0;
    xrn_matrix_traverse( xrn_matrix, &hint, &shared.distance, &shared.distance, &constant_execution,
                         &force_linearity, &check_sparcity );
    force_linearity = 1;

    state_size = ( uint64_t ) settings.state_size + 1;
    hidden_state.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( NULL == hidden_state.xnums ) {
        XPRINT_ERR( 1131, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = expand_xnum( xrn_matrix, shared.distance, &hidden_state, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1132, XERR_GENERAL_MSG );
        return ret;
    }

    ret = loop_enc_stream( fpi, fpo, &hidden_state, xrn_matrix, init_vector, enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1133, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
    return final_ret;

}

int xrn_encrypt_asymmetric_wrapper( FILE * fpi,
                                    FILE * xrn_matrix_fp,
                                    FILE * binomial_key_fp, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xbinomial_key_t bk;
    xrn_matrix_t *xrn_matrix;
    int final_ret, ret;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( binomial_key_fp == NULL ) || ( xrn_matrix_fp == NULL ) ) {
        XPRINT_ERR( 1134, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1135, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1136, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1137, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_binomial_key( &bk, binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1138, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_encrypt_asymmetric( fpi, xrn_matrix, bk, fpo, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1139, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_decrypt_symmetric_wrapper( FILE * fpi,
                                   FILE * xrn_matrix_fp,
                                   FILE * monomial_key_fp, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t mkey;
    int final_ret, ret;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( monomial_key_fp == NULL ) || ( xrn_matrix_fp == NULL ) ) {
        XPRINT_ERR( 1289, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1290, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1291, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1292, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1293, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_decrypt_symmetric( fpi, xrn_matrix, mkey, fpo, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1294, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_encrypt_symmetric_wrapper( FILE * fpi,
                                   FILE * xrn_matrix_fp,
                                   FILE * monomial_key_fp, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_matrix_t *xrn_matrix;
    xmonomial_key_t mkey;
    int final_ret, ret;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( monomial_key_fp == NULL ) || ( xrn_matrix_fp == NULL ) ) {
        XPRINT_ERR( 1318, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1319, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1320, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1321, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1322, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_encrypt_symmetric( fpi, xrn_matrix, mkey, fpo, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1323, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_check_ring_signature( FILE * input_file_fpr,
                              xring_signature_t ring_sig,
                              xmonomial_key_t monomial_key,
                              xrn_matrix_t * xrn_matrix, xbinomial_key_t * tx_binomial_key,
                              xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t i, neq, found;
    xbinomial_key_t rx_binomial_key;
    xhash_t hash;
    xnum_t tmp, zero, proof0, proof1, proof_point;
    xmonomial_key_t shared_key;
    xstart_point_t start_point;
    int final_ret, ret, error0, error1, index_binomial_key;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( input_file_fpr == NULL ) || ( tx_binomial_key == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1449, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    force_linearity = 1;
    constant_execution = settings.const_exec_time;
    check_sparcity = 1;

    // check ring signature size

    if ( ( ring_sig.ring_size < XRN_MIN_RING_SIG_SIZE ) || ( ring_sig.ring_size > XRN_MAX_RING_SIG_SIZE ) ) {
        XPRINT_ERR( 1450, XERR_RING_SIG_SIZE_MSG );
        return XERR_RING_SIG_SIZE;
    }

    xrn_initialize_num( &zero );

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1451, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1452, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1453, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // perform hash of the message file    

    ret = xrn_make_hash( input_file_fpr, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1454, XERR_GENERAL_MSG );
        return ret;
    }

    // check start points

    neq = 0;
    for ( i = 0; ( i < ring_sig.ring_size - 1 ) && ( !neq ); i++ ) {
        XNUM_CMP( ring_sig.binomial_keys[i + 1].start, ring_sig.binomial_keys[i].start, neq );

        if ( neq == 1 ) {

            XPRINT_ERR( 1455, XERR_STARTS_MSG );
            return XERR_STARTS;

        }

    }

    // regenerate binomial key

    start_point.start = ring_sig.binomial_keys[0].start;

    ret = xrn_make_binomial_key( xrn_matrix, start_point, monomial_key, &rx_binomial_key, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1456, XERR_GENERAL_MSG );
        return ret;
    }

    // get index of your binomial key

    found = 0;
    index_binomial_key = -1;

    for ( i = 0; ( i < ring_sig.ring_size ) && ( !found ); i++ ) {
        XNUM_CMP( rx_binomial_key.end, ring_sig.binomial_keys[i].end, neq );
        found = !neq;
        if ( found == 1 ) {
            index_binomial_key = ( int ) i;
        }

    }

    if ( index_binomial_key == -1 ) {
        XPRINT_NOT( 1 );
        ret = ( int ) XWAR_SIG;
        return ret;
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    found = 0;

    // loop for all the binomial keys

    for ( i = 0; ( i < ring_sig.ring_size ) && ( !found ); i++ ) {

        if ( i != index_binomial_key ) {

            // compute shared key
            ret =
                xrn_exchange_monomial_key( xrn_matrix, rx_binomial_key, ring_sig.binomial_keys[i],
                                           monomial_key, &shared_key, settings );

            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 1457, XERR_GENERAL_MSG );
                return ret;
            }

            X_XOR3( shared_key.distance, hash.value, tmp );

            // calculate proof point

            ret =
                xrn_matrix_traverse( xrn_matrix, &ring_sig.hint, &tmp, &proof_point, &constant_execution,
                                     &force_linearity, &check_sparcity );

            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 1458, XERR_GENERAL_MSG );
                return ret;
            }

            // calculate first proof

            ret =
                xrn_matrix_traverse( xrn_matrix, &ring_sig.binomial_keys[i].end, &ring_sig.proof,
                                     &proof1, &constant_execution, &force_linearity, &check_sparcity );

            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 1459, XERR_GENERAL_MSG );
                return ret;
            }

            // calculate second proof

            ret =
                xrn_matrix_traverse( xrn_matrix, &proof_point, &ring_sig.proof, &proof0,
                                     &constant_execution, &force_linearity, &check_sparcity );

            final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
            if ( final_ret == XERR_GENERAL ) {
                XPRINT_ERR( 1460, XERR_GENERAL_MSG );
                return ret;
            }

            XNUM_CMP( proof0, ring_sig.binomial_keys[i].end, error0 );
            XNUM_CMP( proof1, proof_point, error1 );

            if ( !( error0 && error1 ) ) {
                *tx_binomial_key = ring_sig.binomial_keys[i];
                found = 1;

            }

        }

    }

    if ( found == 0 ) {
        XPRINT_NOT( 1 );
        ret = ( int ) XWAR_SIG;
    } else {
        XPRINT_NOT( 0 );
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    return final_ret;

}

int xrn_check_ring_signature_wrapper( FILE * input_file_fpr,
                                      FILE * ring_signature_fpr,
                                      FILE * monomial_key_fpr,
                                      FILE * xrn_matrix_fpr,
                                      FILE * tx_binomial_key_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_key_t mkey;
    xring_signature_t ring_sig;
    xrn_matrix_t *xrn_matrix;
    xbinomial_key_t bkey_tx;
    int final_ret, ret;

    if ( ( input_file_fpr == NULL ) || ( ring_signature_fpr == NULL ) || ( monomial_key_fpr == NULL )
         || ( xrn_matrix_fpr == NULL ) || ( tx_binomial_key_fpw == NULL ) ) {
        XPRINT_ERR( 1470, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1471, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load monomial key
    ret = xrn_load_monomial_key( &mkey, monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1472, XERR_GENERAL_MSG );
        return ret;
    }

    // load ring signature key
    ret = xrn_load_ring_signature( &ring_sig, ring_signature_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1473, XERR_GENERAL_MSG );
        return ret;
    }

    // check ring signature size

    if ( ( ring_sig.ring_size < XRN_MIN_RING_SIG_SIZE ) || ( ring_sig.ring_size > XRN_MAX_RING_SIG_SIZE ) ) {

        XPRINT_ERR( 1474, XERR_RING_SIG_SIZE_MSG );
        return XERR_RING_SIG_SIZE;
    }

    // get xoron matrix

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {

        XPRINT_ERR( 1475, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {

        // free ring signature binomial key

        XRN_FREE( xrn_matrix );

        XPRINT_ERR( 1476, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_ring_signature( input_file_fpr, ring_sig, mkey, xrn_matrix, &bkey_tx, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );

    // free xoron matrix

    XRN_FREE( xrn_matrix );

    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1477, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_binomial_key( bkey_tx, tx_binomial_key_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1478, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_ring_signature( FILE * input_file_fpr,
                             xbinomial_key_t * binomial_key_decoys,
                             xmonomial_key_t monomial_key,
                             xbinomial_key_t tx_binomial_key,
                             xbinomial_key_t rx_binomial_key,
                             xrn_matrix_t * xrn_matrix,
                             uint16_t ndecoys, xring_signature_t * ring_signature,
                             xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_key_t shared_key;
    xring_signature_t ring_sig;
    xhash_t hash;
    xnum_t hint, zero, tmp, proof, xnum_rnd;
    uint64_t i, j;
    int error, greater;
    int final_ret, ret, carry;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( input_file_fpr == NULL ) || ( binomial_key_decoys == NULL ) || ( xrn_matrix == NULL )
         || ( ring_signature == NULL ) ) {
        XPRINT_ERR( 1492, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check ring signature size

    if ( ( ndecoys + 2 < XRN_MIN_RING_SIG_SIZE ) || ( ndecoys + 2 > XRN_MAX_RING_SIG_SIZE ) ) {
        XPRINT_ERR( 1493, XERR_RING_SIG_SIZE_MSG );
        return XERR_RING_SIG_SIZE;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1494, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1495, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1496, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ring_sig.ring_size = ( uint8_t ) ( ndecoys + 2 );

    // initialize a ring signature data structure

    for ( i = 0; i < ndecoys; i++ ) {

        ring_sig.binomial_keys[i] = binomial_key_decoys[i];

        // check for uncommon starts
        if ( i > 0 ) {
            j = i - 1;
            XNUM_CMP( ring_sig.binomial_keys[i].start, ring_sig.binomial_keys[j].start, error );
            if ( error != 0 ) {
                XPRINT_ERR( 1498, XERR_STARTS_MSG );
                return XERR_STARTS;
            }

        }

    }

    ring_sig.binomial_keys[ndecoys] = rx_binomial_key;

    // check for uncommon starts
    j = ( uint64_t ) ndecoys - 1;
    XNUM_CMP( ring_sig.binomial_keys[ndecoys].start, ring_sig.binomial_keys[j].start, error );
    if ( error != 0 ) {
        XPRINT_ERR( 1499, XERR_STARTS_MSG );
        return XERR_STARTS;
    }

    ring_sig.binomial_keys[ndecoys + 1] = tx_binomial_key;

    // check for uncommon starts
    j = ( uint64_t ) ndecoys + 1;
    XNUM_CMP( ring_sig.binomial_keys[j].start, ring_sig.binomial_keys[ndecoys].start, error );
    if ( error != 0 ) {
        XPRINT_ERR( 1500, XERR_STARTS_MSG );
        return XERR_STARTS;
    }

    // check for uncommon ends
    for ( i = 0; i < ndecoys + 2; i++ ) {
        for ( j = i + 1; j < ndecoys + 2; j++ ) {
            XNUM_CMP( ring_sig.binomial_keys[i].end, ring_sig.binomial_keys[j].end, error );
            if ( error == 0 ) {
                XPRINT_ERR( 602, XERR_ENDS_MSG );
                return XERR_ENDS;
            }

        }

    }

    // compute hash of the message
    xrn_initialize_num( &hash.value );
    ret = xrn_make_hash( input_file_fpr, xrn_matrix, &hash, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1501, XERR_GENERAL_MSG );
        return ret;
    }

    // generate common key
    xrn_initialize_num( &shared_key.distance );
    ret =
        xrn_exchange_monomial_key( xrn_matrix, tx_binomial_key, rx_binomial_key, monomial_key, &shared_key,
                                   settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1502, XERR_GENERAL_MSG );
        return ret;
    }

    // get random number
    ret = xrn_initialize_true_rnd_num( "", &xnum_rnd );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1503, XERR_GENERAL_MSG );
        return ret;
    }

    // compute hint point
    ret =
        xrn_matrix_traverse( xrn_matrix, &rx_binomial_key.start, &xnum_rnd, &hint, &constant_execution,
                             &force_linearity, &check_sparcity );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1504, XERR_GENERAL_MSG );
        return ret;
    }

    ring_sig.hint = hint;

    // calculate distance

    X_XOR3( shared_key.distance, hash.value, tmp );

    xrn_initialize_num( &zero );
    carry = xrn_add_nums( tmp, xnum_rnd, 0, &tmp );
    while ( carry == 1 ) {

        carry = xrn_add_nums( tmp, zero, 1, &tmp );

    }

    xrn_compare_greater_equal_nums( tmp, monomial_key.distance, &greater );

    // invert distance

    if ( greater == 1 ) {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( tmp, monomial_key.distance, &proof );

    } else {

        // calculate distance between the previous sum and monomial key
        xrn_subtract_nums( monomial_key.distance, tmp, &proof );

    }

    ring_sig.proof = proof;

    *ring_signature = ring_sig;

    return final_ret;

}

int xrn_make_ring_signature_wrapper( FILE * input_fp,
                                     FILE ** binomial_key_decoys_fp,
                                     FILE * monomial_key_fp,
                                     FILE * tx_binomial_key_fp,
                                     FILE * rx_binomial_key_fp,
                                     FILE * xrn_matrix_fp,
                                     uint16_t ndecoys, FILE * signature_fp,
                                     xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t i;
    xmonomial_key_t mkey;
    xbinomial_key_t rx_bk, tx_bk;
    xrn_matrix_t *xrn_matrix;
    xbinomial_key_t *binomial_keys;
    xring_signature_t ring_sig;
    int final_ret, ret;

    // check for null pointers

    if ( ( xrn_matrix_fp == NULL ) || ( monomial_key_fp == NULL ) || ( binomial_key_decoys_fp == NULL )
         || ( tx_binomial_key_fp == NULL ) || ( rx_binomial_key_fp == NULL ) || ( input_fp == NULL )
         || ( signature_fp == NULL ) ) {
        XPRINT_ERR( 1518, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check ring signature size

    if ( ( ndecoys + 2 < XRN_MIN_RING_SIG_SIZE ) || ( ndecoys + 2 > XRN_MAX_RING_SIG_SIZE ) ) {
        XPRINT_ERR( 1519, XERR_RING_SIG_SIZE_MSG );
        return XERR_RING_SIG_SIZE;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1520, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    for ( i = 0; i < ndecoys; i++ ) {
        if ( binomial_key_decoys_fp[i] == NULL ) {
            XPRINT_ERR( 1521, XERR_NULL_MSG );
            return XERR_NULL;
        }

    }

    // load monomial key

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1522, XERR_GENERAL_MSG );
        return ret;
    }

    // load rx binomial key

    ret = xrn_load_binomial_key( &rx_bk, rx_binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1523, XERR_GENERAL_MSG );
        return ret;
    }

    // load tx binomial key
    ret = xrn_load_binomial_key( &tx_bk, tx_binomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1524, XERR_GENERAL_MSG );
        return ret;
    }

    // get xoron matrix

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1525, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1526, XERR_GENERAL_MSG );
        return ret;
    }

    // load decoys

    binomial_keys = ( xbinomial_key_t * ) malloc( sizeof( xbinomial_key_t ) * ( ndecoys ) );
    if ( binomial_keys == NULL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1527, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < ndecoys; i++ ) {

        ret = xrn_load_binomial_key( &binomial_keys[i], binomial_key_decoys_fp[i], &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {

            XRN_FREEN( binomial_keys, sizeof( xbinomial_key_t ) * ( ndecoys ) );
            XRN_FREE( xrn_matrix );

            XPRINT_ERR( 1528, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // initialize a ring signature data structure

    ret =
        xrn_make_ring_signature( input_fp, binomial_keys, mkey, tx_bk, rx_bk, xrn_matrix, ndecoys, &ring_sig,
                                 settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {

        XRN_FREEN( binomial_keys, sizeof( xbinomial_key_t ) * ( ndecoys ) );
        XRN_FREE( xrn_matrix );

        XPRINT_ERR( 1529, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREEN( binomial_keys, sizeof( xbinomial_key_t ) * ( ndecoys ) );
    XRN_FREE( xrn_matrix );

    // dump ring signature
    ret = xrn_dump_ring_signature( ring_sig, 1, signature_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1530, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_binomial_key_wrapper( FILE * xrn_matrix_fp, FILE * start_point_fp, FILE * monomial_key_fp,
                                   FILE * binomial_key_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );
    xrn_matrix_t *xrn_matrix;
    xstart_point_t start;
    xmonomial_key_t mkey;
    xbinomial_key_t pub;
    int i, final_ret, ret;

    if ( ( xrn_matrix_fp == NULL ) || ( monomial_key_fp == NULL )
         || ( binomial_key_fp == NULL ) || ( start_point_fp == NULL ) ) {
        XPRINT_ERR( 1531, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( start ); i++ ) {
        ( ( uint8_t * ) & start )[i] = 0;
    }

    for ( i = 0; i < sizeof( mkey ); i++ ) {
        ( ( uint8_t * ) & mkey )[i] = 0;
    }

    for ( i = 0; i < sizeof( pub ); i++ ) {
        ( ( uint8_t * ) & pub )[i] = 0;
    }

    final_ret = XSUCCESS;

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1532, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fp, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1533, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_start_point( &start, start_point_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1534, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &mkey, monomial_key_fp, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1535, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_make_binomial_key( xrn_matrix, start, mkey, &pub, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1536, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_binomial_key( pub, binomial_key_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1537, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;
}

int xrn_make_monomial_key_wrapper( FILE * monomial_key_fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_key_t mkey;
    int i, final_ret, ret;

    if ( monomial_key_fp == NULL ) {
        XPRINT_ERR( 1538, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( mkey ); i++ ) {
        ( ( uint8_t * ) & mkey )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1539, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = xrn_make_monomial_key( &mkey, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1540, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_monomial_key( mkey, monomial_key_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1541, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_make_start_point_wrapper( FILE * start_point_fp, FILE * xrn_matrix_fpr, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xstart_point_t orig;
    int i, final_ret, ret;
    xrn_matrix_t *xrn_matrix;

    if ( ( start_point_fp == NULL ) || ( xrn_matrix_fpr == NULL ) ) {
        XPRINT_ERR( 1542, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( orig ); i++ ) {
        ( ( uint8_t * ) & orig )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1543, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1544, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1545, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_make_start_point( &orig, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1546, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_dump_start_point( orig, start_point_fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1547, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_make_monomial_key( xmonomial_key_t * mkey, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, final_ret, ret;
    xmonomial_key_t mkeyl;

    if ( mkey == NULL ) {
        XPRINT_ERR( 1548, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( mkeyl ); i++ ) {
        ( ( uint8_t * ) & mkeyl )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1549, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // generate confidential monomial key

    ret = XERR_SPARSE_MKEY;
    while ( ret == XERR_SPARSE_MKEY ) {

        ret = xrn_initialize_true_rnd_num( settings.rnd_str, &mkeyl.distance );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1550, XERR_GENERAL_MSG );
            return XERR_GENERAL;
        }

        // check monomial key sparsity

        ret = xrn_check_sparsity( mkeyl.distance );

    }

    *mkey = mkeyl;

    return final_ret;
}

int xrn_make_start_point( xstart_point_t * start, xrn_matrix_t * xrn_matrix, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, final_ret, ret;
    xnum_t tmp;
    xrn_log_t xlog2;

    if ( ( start == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1551, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( tmp ); i++ ) {
        ( ( uint8_t * ) & tmp )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1552, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1553, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1554, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = XERR_NLINEAR_START;
    while ( ret == XERR_NLINEAR_START ) {

        ret = xrn_initialize_true_rnd_num( settings.rnd_str, &tmp );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1555, XERR_GENERAL_MSG );
            return ret;
        }

        // check non linearity

        ret = non_linear_start_check( tmp, xrn_matrix );
    }

    start->start = tmp;

    return final_ret;
}

int xrn_make_binomial_key( xrn_matrix_t * xrn_matrix, xstart_point_t start, xmonomial_key_t mkey,
                           xbinomial_key_t * bkey, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int i, final_ret, ret;
    xbinomial_key_t bkey_tmp;
    uint8_t constant_execution, force_linearity, check_sparcity;
    xrn_log_t xlog2;

    if ( ( xrn_matrix == NULL ) || ( bkey == NULL ) ) {
        XPRINT_ERR( 1556, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( bkey_tmp ); i++ ) {
        ( ( uint8_t * ) & bkey_tmp )[i] = 0;
    }

    final_ret = XSUCCESS;
    constant_execution = settings.const_exec_time;
    force_linearity = 1;
    check_sparcity = 1;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1557, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1558, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );
        if ( XSUCCESS != ret ) {
            XPRINT_ERR( 1559, XERR_GENERAL_MSG );
            return ret;
        }

    }

    ret = XERR_NLINEAR_START;
    while ( ret == XERR_NLINEAR_START ) {

        // binomial key
        ret =
            xrn_matrix_traverse( xrn_matrix, &start.start, &mkey.distance, &bkey_tmp.end,
                                 &constant_execution, &force_linearity, &check_sparcity );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1560, XERR_GENERAL_MSG );
            return ret;
        }

        // check non linearity

        ret = non_linear_start_check( bkey_tmp.end, xrn_matrix );
    }

    // assign start
    bkey_tmp.start = start.start;

    *bkey = bkey_tmp;

    return final_ret;

}

int xrn_encrypt_symmetric( FILE * fpi,
                           xrn_matrix_t * xrn_matrix,
                           xmonomial_key_t monomial_key, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_lib_xtype_t type;
    xnum_t init_vector;
    xstate_t hidden_state;
    uint64_t state_size;
    int final_ret, ret;
    xrn_encoding_param_t enc_param;
    xrn_log_t xlog2;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1561, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1562, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1563, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1564, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // dump headers

    type = c_sym_encryption;
    ret = xrn_dump_header_file( fpo, type, settings.crc_bytes, settings.state_size, &enc_param, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 753, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 1566, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // Write initialization vector 

    ret = xrn_initialize_true_rnd_num( settings.rnd_str, &init_vector );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1570, XERR_GENERAL_MSG );
        return ret;
    }

    if ( 1 != xrn_fwrite_encoder( &init_vector, sizeof( xnum_t ) - sizeof( uint64_t ), 1, fpo, &enc_param ) ) {
        XPRINT_ERR( 1571, XERR_IO_MSG );
        return XERR_IO;
    }

    state_size = ( uint64_t ) settings.state_size + 1;
    hidden_state.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( NULL == hidden_state.xnums ) {
        XPRINT_ERR( 1572, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = expand_xnum( xrn_matrix, monomial_key.distance, &hidden_state, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1573, XERR_GENERAL_MSG );
        return ret;
    }

    ret = loop_enc_stream( fpi, fpo, &hidden_state, xrn_matrix, init_vector, enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1574, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
    return final_ret;

}

int xrn_decrypt_symmetric( FILE * fpi,
                           xrn_matrix_t * xrn_matrix,
                           xmonomial_key_t monomial_key, FILE * fpo, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xnum_t init_vector;
    xstate_t hidden_state;
    uint64_t state_size;
    int final_ret, ret;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;
    xrn_log_t xlog2;

    if ( ( fpi == NULL ) || ( fpo == NULL ) || ( xrn_matrix == NULL ) ) {
        XPRINT_ERR( 1575, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1576, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1577, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 1578, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1579, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load header

    exp_type = c_sym_encryption;
    ret =
        xrn_load_header_file( fpi, &crc_bytes_header, &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 715, XERR_GENERAL_MSG );
        return ret;
    }

    settings.crc_bytes = crc_bytes_header;
    settings.state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1587, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // read initialization vector 

    if ( 1 != xrn_fread_decoder( &init_vector, sizeof( xnum_t ) - sizeof( uint64_t ), 1, fpi, &enc_param ) ) {
        XPRINT_ERR( 1588, XERR_IO_MSG );
        return XERR_IO;
    }

    state_size = ( uint64_t ) settings.state_size + 1;
    hidden_state.xnums = ( xnum_t * ) malloc( sizeof( xnum_t ) * state_size );
    if ( NULL == hidden_state.xnums ) {
        XPRINT_ERR( 1589, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = expand_xnum( xrn_matrix, monomial_key.distance, &hidden_state, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1590, XERR_GENERAL_MSG );
        return ret;
    }

    ret = loop_dec_stream( fpi, fpo, &hidden_state, xrn_matrix, init_vector, enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );
        XPRINT_ERR( 1591, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE_XSTATE( hidden_state.xnums, settings.state_size );

    return final_ret;

}

int xrn_make_certificate_asymmetric_wrapper( FILE * issuer_monomial_key_fpr,
                                             FILE * issuer_binomial_key_fpr,
                                             FILE * subject_binomial_key_fpr,
                                             char *subject,
                                             FILE * xrn_matrix_fpr,
                                             uint64_t start_validity,
                                             uint64_t end_validity,
                                             FILE * certificate_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xbinomial_key_t issuer_binomial_key;
    xmonomial_key_t issuer_monomial_key;
    xbinomial_key_t user;
    xcertificate_asy_t certificate;
    xrn_matrix_t *xrn_matrix;
    int final_ret, ret;
    int i;

    if ( ( issuer_binomial_key_fpr == NULL ) || ( subject_binomial_key_fpr == NULL )
         || ( issuer_monomial_key_fpr == NULL )
         || ( certificate_fpw == NULL ) || ( xrn_matrix_fpr == NULL ) || ( subject == NULL ) ) {
        XPRINT_ERR( 1592, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( issuer_binomial_key ); i++ ) {
        ( ( uint8_t * ) & issuer_binomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( issuer_monomial_key ); i++ ) {
        ( ( uint8_t * ) & issuer_monomial_key )[i] = 0;
    }

    for ( i = 0; i < sizeof( user ); i++ ) {
        ( ( uint8_t * ) & user )[i] = 0;
    }

    for ( i = 0; i < sizeof( certificate ); i++ ) {
        ( ( uint8_t * ) & certificate )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1593, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1594, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1595, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_binomial_key( &issuer_binomial_key, issuer_binomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1596, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &issuer_monomial_key, issuer_monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1597, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_binomial_key( &user, subject_binomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1598, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_make_certificate_asymmetric( issuer_monomial_key, issuer_binomial_key, user, subject, xrn_matrix,
                                         start_validity, end_validity, &certificate, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1599, XERR_GENERAL_MSG );
        return ret;

    }

    ret = xrn_dump_certificate_asy( certificate, certificate_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1600, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_make_certificate_symmetric_wrapper( FILE * issuer_monomial_key_fpr,
                                            FILE * subject_monovalent_key_fpr,
                                            char *subject,
                                            FILE * xrn_matrix_fpr,
                                            uint64_t start_validity,
                                            uint64_t end_validity,
                                            FILE * certificate_fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xmonomial_key_t issuer;
    xmonovalent_key_t user;
    xcertificate_sym_t certificate;
    xrn_matrix_t *xrn_matrix;
    int final_ret, ret;
    int i;

    if ( ( issuer_monomial_key_fpr == NULL ) || ( subject_monovalent_key_fpr == NULL )
         || ( certificate_fpw == NULL ) || ( xrn_matrix_fpr == NULL ) || ( subject == NULL ) ) {
        XPRINT_ERR( 1601, XERR_NULL_MSG );
        return XERR_NULL;
    }

    for ( i = 0; i < sizeof( certificate ); i++ ) {
        ( ( uint8_t * ) & certificate )[i] = 0;
    }

    for ( i = 0; i < sizeof( issuer ); i++ ) {
        ( ( uint8_t * ) & issuer )[i] = 0;
    }

    for ( i = 0; i < sizeof( user ); i++ ) {
        ( ( uint8_t * ) & user )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1602, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1603, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1604, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &issuer, issuer_monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1605, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monovalent_key( &user, subject_monovalent_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1606, XERR_GENERAL_MSG );
        return ret;
    }

    ret =
        xrn_make_certificate_symmetric( issuer, user, subject, xrn_matrix, start_validity, end_validity,
                                        &certificate, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1607, XERR_GENERAL_MSG );
        return ret;

    }

    ret = xrn_dump_certificate_sym( certificate, certificate_fpw, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1608, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_make_certificate_asymmetric( xmonomial_key_t issuer_monomial_key,
                                     xbinomial_key_t issuer_binomial_key,
                                     xbinomial_key_t subject_binomial_key,
                                     char *subject,
                                     xrn_matrix_t * xrn_matrix,
                                     uint64_t start_validity,
                                     uint64_t end_validity,
                                     xcertificate_asy_t * certificate, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xsignature_asy_t signature;
    uint64_t i;
    int final_ret, ret;
    xrn_log_t xlog2;

    struct certificate_t {
        xbinomial_key_t binomial_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( ( certificate == NULL ) || ( xrn_matrix == NULL ) || ( subject == NULL ) ) {
        XPRINT_ERR( 1609, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( end_validity < start_validity ) {
        XPRINT_ERR( 85, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( certificate_tmp ); i++ ) {
        ( ( uint8_t * ) & certificate_tmp )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1610, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1611, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1612, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( strnlen( subject, XRN_SUBJECT_CERTIFICATE_LENGTH ) > XRN_SUBJECT_CERTIFICATE_LENGTH ) {
        XPRINT_ERR( 1613, XERR_SUBJECT_MSG );
        return XERR_SUBJECT;
    }

    // prepare data structure

    certificate_tmp.binomial_key = subject_binomial_key;
    certificate_tmp.start_timestamp = start_validity;
    certificate_tmp.end_timestamp = end_validity;
    for ( i = 0; i < XRN_SUBJECT_CERTIFICATE_LENGTH; i++ ) {
        certificate_tmp.subject[i] = 0;
    }

    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", subject );

    // calculate signature

    ret =
        xrn_make_signature_asymmetric_bytes( ( uint8_t * ) & certificate_tmp, sizeof( certificate_tmp ),
                                             issuer_monomial_key, issuer_binomial_key, xrn_matrix, &signature,
                                             settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1614, XERR_GENERAL_MSG );
        return ret;
    }

    // assign output

    snprintf( certificate->subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate_tmp.subject );

    certificate->binomial_key = certificate_tmp.binomial_key;
    certificate->start_timestamp = certificate_tmp.start_timestamp;
    certificate->end_timestamp = certificate_tmp.end_timestamp;
    certificate->signature = signature;

    return final_ret;

}

int xrn_make_certificate_symmetric( xmonomial_key_t issuer_key,
                                    xmonovalent_key_t subject_monovalent_key,
                                    char *subject,
                                    xrn_matrix_t * xrn_matrix,
                                    uint64_t start_validity,
                                    uint64_t end_validity,
                                    xcertificate_sym_t * certificate, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xsignature_sym_t signature;
    uint64_t i;
    int final_ret, ret;
    xrn_log_t xlog2;

    struct certificate_t {
        xmonovalent_key_t monovalent_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( ( certificate == NULL ) || ( xrn_matrix == NULL ) || ( subject == NULL ) ) {
        XPRINT_ERR( 1615, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( end_validity < start_validity ) {
        XPRINT_ERR( 100, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sizeof( certificate_tmp ); i++ ) {
        ( ( uint8_t * ) & certificate_tmp )[i] = 0;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1616, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1617, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1618, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( issuer_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 1619, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    if ( strnlen( subject, XRN_SUBJECT_CERTIFICATE_LENGTH ) > XRN_SUBJECT_CERTIFICATE_LENGTH ) {
        XPRINT_ERR( 1620, XERR_SUBJECT_MSG );
        return XERR_SUBJECT;
    }

    // prepare datastructure

    certificate_tmp.monovalent_key = subject_monovalent_key;
    certificate_tmp.start_timestamp = start_validity;
    certificate_tmp.end_timestamp = end_validity;
    for ( i = 0; i < XRN_SUBJECT_CERTIFICATE_LENGTH; i++ ) {
        certificate_tmp.subject[i] = 0;
    }

    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", subject );

    // calculate signature
    ret =
        xrn_make_signature_symmetric_bytes( ( uint8_t * ) & certificate_tmp, sizeof( certificate_tmp ),
                                            issuer_key, xrn_matrix, &signature, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1621, XERR_GENERAL_MSG );
        return ret;
    }

    // assign output

    snprintf( certificate->subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate_tmp.subject );

    certificate->monovalent_key = certificate_tmp.monovalent_key;
    certificate->start_timestamp = certificate_tmp.start_timestamp;
    certificate->end_timestamp = certificate_tmp.end_timestamp;
    certificate->signature = signature;

    return final_ret;

}

int xrn_check_certificate_asymmetric_wrapper( FILE * issuer_binomial_key_fpr,
                                              FILE * xrn_matrix_fpr,
                                              FILE * certificate_fpr, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xcertificate_asy_t certificate;
    xbinomial_key_t issuer;
    xrn_matrix_t *xrn_matrix;
    int final_ret, ret;

    if ( ( issuer_binomial_key_fpr == NULL ) || ( certificate_fpr == NULL ) || ( xrn_matrix_fpr == NULL ) ) {
        XPRINT_ERR( 1622, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1623, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1624, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1625, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_binomial_key( &issuer, issuer_binomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1626, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_certificate_asy( &certificate, certificate_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1627, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_certificate_asymmetric( issuer, xrn_matrix, certificate, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1628, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_check_certificate_symmetric_wrapper( FILE * issuer_monomial_key_fpr,
                                             FILE * xrn_matrix_fpr,
                                             FILE * certificate_fpr, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xcertificate_sym_t certificate;
    xmonomial_key_t issuer;
    xrn_matrix_t *xrn_matrix;
    int final_ret, ret;

    if ( ( issuer_monomial_key_fpr == NULL ) || ( certificate_fpr == NULL )
         || ( xrn_matrix_fpr == NULL ) ) {
        XPRINT_ERR( 1629, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1630, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    xrn_matrix = ( xrn_matrix_t * ) malloc( sizeof( xrn_matrix_t ) );

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1631, XERR_NULL_MSG );
        return XERR_NULL;
    }

    ret = xrn_load_matrix( xrn_matrix_fpr, xrn_matrix, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1632, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_monomial_key( &issuer, issuer_monomial_key_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1633, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_certificate_sym( &certificate, certificate_fpr, &settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1634, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_check_certificate_symmetric( issuer, xrn_matrix, certificate, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XRN_FREE( xrn_matrix );
        XPRINT_ERR( 1635, XERR_GENERAL_MSG );
        return ret;
    }

    XRN_FREE( xrn_matrix );
    return final_ret;

}

int xrn_check_certificate_asymmetric( xbinomial_key_t issuer_binomial_key,
                                      xrn_matrix_t * xrn_matrix,
                                      xcertificate_asy_t certificate, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t t;
    xsignature_asy_t signature;
    uint64_t i;
    int final_ret, ret;
    xrn_log_t xlog2;

    struct certificate_t {
        xbinomial_key_t binomial_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1636, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( certificate.end_timestamp <= certificate.start_timestamp ) {
        XPRINT_ERR( 104, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1637, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1638, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1639, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( 0 > time( ( time_t * ) & t ) ) {
        XPRINT_ERR( 1640, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // check time of the certificate
    if ( ( t < certificate.start_timestamp )
         || ( t > certificate.end_timestamp ) ) {
        XPRINT_NOT( 1 );
        XPRINT_WAR( XWAR_TIMING_MSG, XWAR_TIMING );
        return ( int ) XWAR_TIMING;
    }

    // prepare datastructure

    certificate_tmp.binomial_key = certificate.binomial_key;
    certificate_tmp.start_timestamp = certificate.start_timestamp;
    certificate_tmp.end_timestamp = certificate.end_timestamp;
    for ( i = 0; i < XRN_SUBJECT_CERTIFICATE_LENGTH; i++ ) {
        certificate_tmp.subject[i] = 0;
    }

    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate.subject );

    signature = certificate.signature;

    // calculate signature

    ret =
        xrn_check_signature_asymmetric_bytes( ( uint8_t * ) & certificate_tmp, sizeof( certificate_tmp ),
                                              issuer_binomial_key, xrn_matrix, signature, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1641, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_check_certificate_symmetric( xmonomial_key_t issuer_monomial_key,
                                     xrn_matrix_t * xrn_matrix,
                                     xcertificate_sym_t certificate, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint64_t t;
    xsignature_sym_t signature;
    uint64_t i;
    int final_ret, ret;
    xrn_log_t xlog2;

    struct certificate_t {
        xmonovalent_key_t monovalent_key;
        char subject[XRN_SUBJECT_CERTIFICATE_LENGTH];
        uint64_t start_timestamp;
        uint64_t end_timestamp;
    } certificate_tmp;

    if ( xrn_matrix == NULL ) {
        XPRINT_ERR( 1642, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( certificate.end_timestamp <= certificate.start_timestamp ) {
        XPRINT_ERR( 244, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = XSUCCESS;

    // check if xoron matrix is correct

    xlog2 = xlog;
    xlog.not_en = 0;
    ret = xrn_matrix_check( xrn_matrix );
    xlog = xlog2;
    if ( XERR_NOT_MATRIX == ret ) {
        XPRINT_ERR( 1643, XERR_NOT_MATRIX_MSG );
        return XERR_NOT_MATRIX;
    }

    // permute xoron matrix

    if ( ( ( ( uint32_t ) ret & 0x00000fff ) != XINFO_PERMUTED_MATRIX ) ) {
        ret = xrn_permute_matrix( xrn_matrix );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1644, XERR_GENERAL_MSG );
            return ret;
        }

    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1645, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( issuer_monomial_key.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 1646, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    if ( 0 > time( ( time_t * ) & t ) ) {
        XPRINT_ERR( 1647, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // check time of the certificate
    if ( ( t < certificate.start_timestamp )
         || ( t > certificate.end_timestamp ) ) {
        XPRINT_NOT( 1 );
        XPRINT_WAR( XWAR_TIMING_MSG, XWAR_TIMING );
        return ( int ) XWAR_TIMING;
    }

    // prepare datastructure

    certificate_tmp.monovalent_key = certificate.monovalent_key;
    certificate_tmp.start_timestamp = certificate.start_timestamp;
    certificate_tmp.end_timestamp = certificate.end_timestamp;
    for ( i = 0; i < XRN_SUBJECT_CERTIFICATE_LENGTH; i++ ) {
        certificate_tmp.subject[i] = 0;
    }

    snprintf( certificate_tmp.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, "%s", certificate.subject );

    signature = certificate.signature;

    // calculate signature

    ret =
        xrn_check_signature_symmetric_bytes( ( uint8_t * ) & certificate_tmp, sizeof( certificate_tmp ),
                                             issuer_monomial_key, xrn_matrix, signature, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1648, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_dump_ring_signature( xring_signature_t sig, XBIT_TYPE shuffle, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    uint32_t crc32_local;
    xring_signature_t sig_shuffled;
    int ret, final_ret, error, i;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1649, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1650, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // dump header

    type = c_ring_signature;
    ret = xrn_dump_header_file( fp, type, settings.crc_bytes, settings.state_size, &enc_param, settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 787, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // check ring signature size

    if ( ( sig.ring_size < XRN_MIN_RING_SIG_SIZE ) || ( sig.ring_size > XRN_MAX_RING_SIG_SIZE ) ) {
        XPRINT_ERR( 1652, XERR_RING_SIG_SIZE_MSG );
        return XERR_RING_SIG_SIZE;
    }

    // shuffle signature

    if ( shuffle ) {
        sig_shuffled = sig;
        if ( shuffle_binomial_keys( &sig_shuffled ) != 0 ) {
            XPRINT_ERR( 1653, XERR_NULL_MSG );
            return XERR_NULL;
        }

    } else {
        sig_shuffled = sig;
    }

    // check that all the starts are the same for all the binomial keys

    for ( i = 1; i < sig_shuffled.ring_size; i++ ) {

        XNUM_CMP( sig_shuffled.binomial_keys[i].start, sig_shuffled.binomial_keys[i - 1].start, error );
        if ( error ) {
            XPRINT_ERR( 1654, XERR_STARTS_MSG );
            return XERR_STARTS;
        }

    }

    // dump signature

    if ( 1 !=
         xrn_fwrite_encoder( &sig_shuffled.ring_size, sizeof( sig_shuffled.ring_size ), 1, fp,
                             &enc_param ) ) {
        XPRINT_ERR( 1657, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &sig_shuffled.hint, sizeof( sig_shuffled.hint ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1658, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &sig_shuffled.proof, sizeof( sig_shuffled.proof ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1659, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fwrite_encoder( &sig_shuffled.binomial_keys[0].start,
                             sizeof( sig_shuffled.binomial_keys[0].start ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1660, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < sig_shuffled.ring_size; i++ ) {

        if ( 1 !=
             xrn_fwrite_encoder( &sig_shuffled.binomial_keys[i].end,
                                 sizeof( sig_shuffled.binomial_keys[i].end ), 1, fp, &enc_param ) ) {
            XPRINT_ERR( 1076, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // dump crc

    crc32_local = 0xffffffff;
    xrn_crc32( ( uint8_t * ) & sig_shuffled.ring_size, sizeof( sig_shuffled.ring_size ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & sig_shuffled.hint, sizeof( sig_shuffled.hint ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & sig_shuffled.proof, sizeof( sig_shuffled.proof ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & sig_shuffled.binomial_keys[0].start, sizeof( sig_shuffled.proof ),
               &crc32_local );

    for ( i = 0; i < sig_shuffled.ring_size; i++ ) {
        xrn_crc32( ( uint8_t * ) & sig_shuffled.binomial_keys[i].end,
                   sizeof( sig_shuffled.binomial_keys[i].end ), &crc32_local );
    }

    if ( 1 != xrn_fwrite_encoder( &crc32_local, sizeof( crc32_local ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1662, XERR_IO_MSG );
        return XERR_IO;
    }

    return final_ret;

}

int xrn_load_ring_signature( xring_signature_t * sig, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    int i, ret, final_ret;
    uint32_t crc32_local, crc32_stored;
    xring_signature_t local_sig;
    xnum_t start;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type_header;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;

    if ( ( fp == NULL ) || ( settings == NULL ) || ( sig == NULL ) ) {
        XPRINT_ERR( 1663, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( *settings ) ) {
        XPRINT_ERR( 1664, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_ring_signature;
    ret =
        xrn_load_header_file( fp, &crc_bytes_header,
                              &type_header, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, *settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 792, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    settings->crc_bytes = crc_bytes_header;
    settings->state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( *settings ) ) {
        XPRINT_ERR( 786, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load signature

    if ( 1 != xrn_fread_decoder( &local_sig.ring_size, sizeof( local_sig.ring_size ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1672, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fread_decoder( &local_sig.hint, sizeof( local_sig.hint ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1673, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fread_decoder( &local_sig.proof, sizeof( local_sig.proof ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1674, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fread_decoder( &local_sig.binomial_keys[0].start, sizeof( local_sig.binomial_keys[0].start ), 1,
                            fp, &enc_param ) ) {

        XPRINT_ERR( 1676, XERR_IO_MSG );
        return XERR_IO;
    }

    for ( i = 0; i < local_sig.ring_size; i++ ) {

        if ( 1 !=
             xrn_fread_decoder( &local_sig.binomial_keys[i].end, sizeof( local_sig.binomial_keys[i].end ), 1,
                                fp, &enc_param ) ) {

            XPRINT_ERR( 1677, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // check crc

    crc32_local = 0xffffffff;
    xrn_crc32( ( uint8_t * ) & local_sig.ring_size, sizeof( local_sig.ring_size ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & local_sig.hint, sizeof( local_sig.hint ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & local_sig.proof, sizeof( local_sig.proof ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & local_sig.binomial_keys[0].start, sizeof( local_sig.proof ), &crc32_local );
    for ( i = 0; i < local_sig.ring_size; i++ ) {
        xrn_crc32( ( uint8_t * ) & local_sig.binomial_keys[i].end, sizeof( local_sig.binomial_keys[i].end ),
                   &crc32_local );
    }

    if ( 1 != xrn_fread_decoder( &crc32_stored, sizeof( crc32_stored ), 1, fp, &enc_param ) ) {

        XPRINT_ERR( 1678, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( crc32_stored != crc32_local ) {

        XPRINT_ERR( 1679, XERR_CRC_MSG );
        return XERR_CRC;
    }

    // copy result

    start = local_sig.binomial_keys[0].start;

    for ( i = 0; i < local_sig.ring_size; i++ ) {
        sig->binomial_keys[i].start = start;
        sig->binomial_keys[i].end = local_sig.binomial_keys[i].end;
    }

    sig->hint = local_sig.hint;
    sig->proof = local_sig.proof;
    sig->ring_size = local_sig.ring_size;

    return final_ret;

}

int xrn_dump_certificate_asy( xcertificate_asy_t cert, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );
    int ret, final_ret;
    uint32_t crc32_local;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1682, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( cert.end_timestamp <= cert.start_timestamp ) {
        XPRINT_ERR( 245, XERR_IO_MSG );
        return XERR_IO;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1683, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // dump header

    type = c_certificate_asy;
    ret = xrn_dump_header_file( fp, type, settings.crc_bytes, settings.state_size, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 797, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.binomial_key, sizeof( xbinomial_key_t ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1687, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.subject[0], XRN_SUBJECT_CERTIFICATE_LENGTH, 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1688, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.start_timestamp, sizeof( cert.start_timestamp ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1689, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.end_timestamp, sizeof( cert.end_timestamp ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1690, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.signature, sizeof( cert.signature ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1691, XERR_IO_MSG );
        return XERR_IO;
    }

    // dump crc

    crc32_local = 0xffffffff;
    xrn_crc32( ( uint8_t * ) & cert.binomial_key, sizeof( cert.binomial_key ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.start_timestamp, sizeof( cert.start_timestamp ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.end_timestamp, sizeof( cert.end_timestamp ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.signature, sizeof( cert.signature ), &crc32_local );

    if ( 1 != xrn_fwrite_encoder( &crc32_local, sizeof( crc32_local ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1692, XERR_IO_MSG );
        return XERR_IO;
    }

    return final_ret;

}

int xrn_load_certificate_asy( xcertificate_asy_t * cert, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );
    int ret, final_ret;
    uint32_t crc32_local, crc32_stored;
    xcertificate_asy_t cert_local;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;

    if ( ( fp == NULL ) || ( settings == NULL ) || ( cert == NULL ) ) {
        XPRINT_ERR( 1693, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( *settings ) ) {
        XPRINT_ERR( 1694, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_certificate_asy;
    ret =
        xrn_load_header_file( fp, &crc_bytes_header,
                              &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, *settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 796, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    settings->crc_bytes = crc_bytes_header;
    settings->state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( *settings ) ) {
        XPRINT_ERR( 795, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load certificate

    if ( 1 != xrn_fread_decoder( &cert_local.binomial_key, sizeof( xbinomial_key_t ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1702, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fread_decoder( &cert_local.subject[0], XRN_SUBJECT_CERTIFICATE_LENGTH, 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1703, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fread_decoder( &cert_local.start_timestamp, sizeof( cert_local.start_timestamp ), 1, fp,
                            &enc_param ) ) {
        XPRINT_ERR( 1704, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fread_decoder( &cert_local.end_timestamp, sizeof( cert_local.end_timestamp ), 1, fp,
                            &enc_param ) ) {
        XPRINT_ERR( 1705, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fread_decoder( &cert_local.signature, sizeof( cert_local.signature ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1706, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( cert_local.end_timestamp <= cert_local.start_timestamp ) {
        XPRINT_ERR( 246, XERR_IO_MSG );
        return XERR_IO;
    }

    // dump crc

    crc32_local = 0xffffffff;
    xrn_crc32( ( uint8_t * ) & cert_local.binomial_key, sizeof( cert_local.binomial_key ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.start_timestamp, sizeof( cert_local.start_timestamp ),
               &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.end_timestamp, sizeof( cert_local.end_timestamp ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.signature, sizeof( cert_local.signature ), &crc32_local );

    if ( 1 != xrn_fread_decoder( &crc32_stored, sizeof( crc32_stored ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1707, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( crc32_local != crc32_stored ) {
        XPRINT_ERR( 1708, XERR_CRC_MSG );
        return XERR_CRC;
    }

    *cert = cert_local;

    return final_ret;

}

int xrn_dump_certificate_sym( xcertificate_sym_t cert, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret;
    uint32_t crc32_local;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1709, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1710, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( cert.end_timestamp <= cert.start_timestamp ) {
        XPRINT_ERR( 250, XERR_IO_MSG );
        return XERR_IO;
    }

    // dump header

    type = c_certificate_sym;
    ret = xrn_dump_header_file( fp, type, settings.crc_bytes, settings.state_size, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 793, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // dump certificate

    if ( 1 != xrn_fwrite_encoder( &cert.monovalent_key, sizeof( xmonovalent_key_t ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1714, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1715, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.start_timestamp, sizeof( cert.start_timestamp ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1716, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.end_timestamp, sizeof( cert.end_timestamp ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1717, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fwrite_encoder( &cert.signature, sizeof( cert.signature ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1718, XERR_IO_MSG );
        return XERR_IO;
    }

    // dump crc

    crc32_local = 0xffffffff;
    xrn_crc32( ( uint8_t * ) & cert.monovalent_key, sizeof( cert.monovalent_key ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.start_timestamp, sizeof( cert.start_timestamp ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.end_timestamp, sizeof( cert.end_timestamp ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert.signature, sizeof( cert.signature ), &crc32_local );

    if ( 1 != xrn_fwrite_encoder( &crc32_local, sizeof( crc32_local ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1719, XERR_IO_MSG );
        return XERR_IO;
    }

    return final_ret;

}

int xrn_load_certificate_sym( xcertificate_sym_t * cert, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    int ret, final_ret;
    uint32_t crc32_local, crc32_stored;
    xcertificate_sym_t cert_local;
    xrn_encoding_param_t enc_param;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;

    if ( ( fp == NULL ) || ( settings == NULL ) || ( cert == NULL ) ) {
        XPRINT_ERR( 1720, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( *settings ) ) {
        XPRINT_ERR( 1721, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // load header

    exp_type = c_certificate_sym;
    ret =
        xrn_load_header_file( fp, &crc_bytes_header,
                              &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, *settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 820, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    settings->crc_bytes = crc_bytes_header;
    settings->state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( *settings ) ) {
        XPRINT_ERR( 794, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( 1 !=
         xrn_fread_decoder( &cert_local.monovalent_key, sizeof( xmonovalent_key_t ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1729, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fread_decoder( &cert_local.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1730, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fread_decoder( &cert_local.start_timestamp, sizeof( cert_local.start_timestamp ), 1, fp,
                            &enc_param ) ) {
        XPRINT_ERR( 1731, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 !=
         xrn_fread_decoder( &cert_local.end_timestamp, sizeof( cert_local.end_timestamp ), 1, fp,
                            &enc_param ) ) {
        XPRINT_ERR( 1732, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( 1 != xrn_fread_decoder( &cert_local.signature, sizeof( cert_local.signature ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1733, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( cert_local.end_timestamp <= cert_local.start_timestamp ) {
        XPRINT_ERR( 597, XERR_IO_MSG );
        return XERR_IO;
    }

    // read crc

    crc32_local = 0xffffffff;
    xrn_crc32( ( uint8_t * ) & cert_local.monovalent_key, sizeof( cert_local.monovalent_key ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.subject, XRN_SUBJECT_CERTIFICATE_LENGTH, &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.start_timestamp, sizeof( cert_local.start_timestamp ),
               &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.end_timestamp, sizeof( cert_local.end_timestamp ), &crc32_local );
    xrn_crc32( ( uint8_t * ) & cert_local.signature, sizeof( cert_local.signature ), &crc32_local );

    if ( 1 != xrn_fread_decoder( &crc32_stored, sizeof( crc32_stored ), 1, fp, &enc_param ) ) {
        XPRINT_ERR( 1734, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( crc32_local != crc32_stored ) {
        XPRINT_ERR( 1735, XERR_CRC_MSG );
        return XERR_CRC;
    }

    *cert = cert_local;

    return final_ret;

}

int xrn_dump_monovalent_key( xmonovalent_key_t mkey, FILE * fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret, i;
    xrn_encoding_param_t enc_param;
    uint32_t crc32_local;
    xrn_lib_xtype_t type;

    crc32_local = 0xffffffff;

    final_ret = XSUCCESS;

    if ( fpw == NULL ) {
        XPRINT_ERR( 1736, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1737, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    if ( mkey.end_timestamp <= mkey.start_timestamp ) {
        XPRINT_ERR( 599, XERR_IO_MSG );
        return XERR_IO;
    }

    // dump header

    type = c_monovalent_key;
    ret = xrn_dump_header_file( fpw, type, settings.crc_bytes, settings.state_size, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 798, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // dump timestamps

    if ( 1 !=
         xrn_fwrite_encoder( &mkey.start_timestamp, sizeof( mkey.start_timestamp ), 1, fpw, &enc_param ) ) {
        XPRINT_ERR( 1741, XERR_IO_MSG );
        return XERR_IO;
    }

    xrn_crc32( ( uint8_t * ) & mkey.start_timestamp, sizeof( mkey.start_timestamp ), &crc32_local );

    if ( 1 != xrn_fwrite_encoder( &mkey.end_timestamp, sizeof( mkey.end_timestamp ), 1, fpw, &enc_param ) ) {
        XPRINT_ERR( 1742, XERR_IO_MSG );
        return XERR_IO;
    }

    xrn_crc32( ( uint8_t * ) & mkey.end_timestamp, sizeof( mkey.end_timestamp ), &crc32_local );

    // dump key state
    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

        if ( 1 != xrn_fwrite_encoder( &mkey.state[i], sizeof( xnum_t ), 1, fpw, &enc_param ) ) {
            XPRINT_ERR( 1743, XERR_IO_MSG );
            return XERR_IO;
        }

        xrn_crc32( ( uint8_t * ) & mkey.state[i], sizeof( xnum_t ), &crc32_local );
    }

    if ( 1 != xrn_fwrite_encoder( &crc32_local, sizeof( crc32_local ), 1, fpw, &enc_param ) ) {
        XPRINT_ERR( 1744, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1745, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_dump_polyvalent_proof( xpolyvalent_proof_t pproof, FILE * fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret, i;
    xrn_encoding_param_t enc_param;
    uint32_t crc32_local;
    xrn_lib_xtype_t type;

    crc32_local = 0xffffffff;

    final_ret = XSUCCESS;

    if ( fpw == NULL ) {
        XPRINT_ERR( 1746, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1747, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // dump header

    type = c_polyvalent_proof;
    ret = xrn_dump_header_file( fpw, type, settings.crc_bytes, settings.state_size, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 807, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // dump key state
    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
        if ( 1 != xrn_fwrite_encoder( &pproof.state[i], sizeof( xnum_t ), 1, fpw, &enc_param ) ) {
            XPRINT_ERR( 1751, XERR_IO_MSG );
            return XERR_IO;
        }

        xrn_crc32( ( uint8_t * ) & pproof.state[i], sizeof( xnum_t ), &crc32_local );
    }

    if ( 1 != xrn_fwrite_encoder( &crc32_local, sizeof( crc32_local ), 1, fpw, &enc_param ) ) {
        XPRINT_ERR( 1752, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1753, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_dump_polyvalent_key( xpolyvalent_key_t pstate, FILE * fpw, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret, i;
    xrn_encoding_param_t enc_param;
    uint32_t crc32_local;
    xrn_lib_xtype_t type;

    crc32_local = 0xffffffff;

    final_ret = XSUCCESS;

    if ( fpw == NULL ) {
        XPRINT_ERR( 1754, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1755, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // dump header

    type = c_polyvalent_key;
    ret = xrn_dump_header_file( fpw, type, settings.crc_bytes, settings.state_size, &enc_param, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 808, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    // dump key state
    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
        if ( 1 != xrn_fwrite_encoder( &pstate.state[i], sizeof( xnum_t ), 1, fpw, &enc_param ) ) {
            XPRINT_ERR( 1759, XERR_IO_MSG );
            return XERR_IO;
        }

        xrn_crc32( ( uint8_t * ) & pstate.state[i], sizeof( xnum_t ), &crc32_local );
    }

    if ( 1 != xrn_fwrite_encoder( &crc32_local, sizeof( crc32_local ), 1, fpw, &enc_param ) ) {
        XPRINT_ERR( 1760, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1761, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;

}

int xrn_load_monovalent_key( xmonovalent_key_t * mkey, FILE * fpr, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint32_t crc32_local;
    uint32_t crc32_stored;
    int ret, final_ret, i;
    xrn_encoding_param_t enc_param;
    xmonovalent_key_t mkey_local;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;
    xrn_crypto_extra_settings_t settings_local, settings_local2;

    if ( ( fpr == NULL ) || ( mkey == NULL ) ) {
        XPRINT_ERR( 1762, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;

    settings_local = *settings;

    // load header

    exp_type = c_monovalent_key;
    ret =
        xrn_load_header_file( fpr, &crc_bytes_header,
                              &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 825, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    settings_local2 = settings_local;
    settings_local2.crc_bytes = crc_bytes_header;
    settings_local2.state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local2 ) ) {
        XPRINT_ERR( 821, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    crc32_local = 0xffffffff;

    // load timestamps

    if ( xrn_fread_decoder
         ( &mkey_local.start_timestamp, sizeof( mkey_local.start_timestamp ), 1, fpr, &enc_param )
         != 1 ) {
        XPRINT_ERR( 1770, XERR_IO_MSG );
        return XERR_IO;
    }

    xrn_crc32( ( uint8_t * ) & mkey_local.start_timestamp, sizeof( mkey_local.start_timestamp ),
               &crc32_local );

    if ( xrn_fread_decoder
         ( &mkey_local.end_timestamp, sizeof( mkey_local.end_timestamp ), 1, fpr, &enc_param ) != 1 ) {
        XPRINT_ERR( 1771, XERR_IO_MSG );
        return XERR_IO;
    }

    xrn_crc32( ( uint8_t * ) & mkey_local.end_timestamp, sizeof( mkey_local.end_timestamp ), &crc32_local );

    // load state

    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
        if ( xrn_fread_decoder( &mkey_local.state[i], sizeof( xnum_t ), 1, fpr, &enc_param ) != 1 ) {
            XPRINT_ERR( 1772, XERR_IO_MSG );
            return XERR_IO;
        }

        xrn_crc32( ( uint8_t * ) & mkey_local.state[i], sizeof( xnum_t ), &crc32_local );

    }

    if ( xrn_fread_decoder( &crc32_stored, sizeof( crc32_stored ), 1, fpr, &enc_param ) != 1 ) {
        XPRINT_ERR( 1773, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( crc32_stored != crc32_local ) {
        XPRINT_ERR( 1774, XERR_CRC_MSG );
        return XERR_CRC;
    }

    if ( mkey_local.end_timestamp <= mkey_local.start_timestamp ) {
        XPRINT_ERR( 601, XERR_IO_MSG );
        return XERR_IO;
    }

    *mkey = mkey_local;
    *settings = settings_local;

    return final_ret;

}

int xrn_load_polyvalent_proof( xpolyvalent_proof_t * pproof, FILE * fpr, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint32_t crc32_local;
    uint32_t crc32_stored;
    int ret, final_ret, i;
    xrn_encoding_param_t enc_param;
    xpolyvalent_proof_t pproof_local;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;
    xrn_crypto_extra_settings_t settings_local, settings_local2;

    if ( ( fpr == NULL ) || ( pproof == NULL ) ) {
        XPRINT_ERR( 1775, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    settings_local = *settings;

    // load header

    exp_type = c_polyvalent_proof;
    ret =
        xrn_load_header_file( fpr, &crc_bytes_header,
                              &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 826, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    settings_local2 = settings_local;
    settings_local2.crc_bytes = crc_bytes_header;
    settings_local2.state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local2 ) ) {
        XPRINT_ERR( 824, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    crc32_local = 0xffffffff;

    // load state

    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

        if ( xrn_fread_decoder( &pproof_local.state[i], sizeof( xnum_t ), 1, fpr, &enc_param ) != 1 ) {
            XPRINT_ERR( 1783, XERR_IO_MSG );
            return XERR_IO;
        }

        xrn_crc32( ( uint8_t * ) & pproof_local.state[i], sizeof( xnum_t ), &crc32_local );

    }

    if ( xrn_fread_decoder( &crc32_stored, sizeof( crc32_stored ), 1, fpr, &enc_param ) != 1 ) {
        XPRINT_ERR( 1784, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( crc32_stored != crc32_local ) {
        XPRINT_ERR( 1785, XERR_CRC_MSG );
        return XERR_CRC;
    }

    *pproof = pproof_local;
    *settings = settings_local;

    return final_ret;

}

int xrn_load_polyvalent_key( xpolyvalent_key_t * pkey, FILE * fpr, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint32_t crc32_local;
    uint32_t crc32_stored;
    int ret, final_ret, i;
    xrn_encoding_param_t enc_param;
    xpolyvalent_key_t pkey_local;
    xrn_lib_xtype_t exp_type;
    xrn_lib_xtype_t type;
    uint8_t crc_bytes_header;
    uint8_t state_size_header;
    uint32_t reserved_0, reserved_1;
    xrn_crypto_extra_settings_t settings_local, settings_local2;

    if ( ( fpr == NULL ) || ( pkey == NULL ) ) {
        XPRINT_ERR( 1786, XERR_NULL_MSG );
        return XERR_NULL;
    }

    final_ret = XSUCCESS;
    settings_local = *settings;

    // load header

    exp_type = c_polyvalent_key;
    ret =
        xrn_load_header_file( fpr, &crc_bytes_header,
                              &type, exp_type,
                              &state_size_header, &reserved_0, &reserved_1, &enc_param, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 827, XERR_GENERAL_MSG );
        return XERR_GENERAL;
    }

    settings_local2 = settings_local;
    settings_local2.crc_bytes = crc_bytes_header;
    settings_local2.state_size = state_size_header;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local2 ) ) {
        XPRINT_ERR( 791, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    crc32_local = 0xffffffff;

    // load state

    for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {

        if ( xrn_fread_decoder( &pkey_local.state[i], sizeof( xnum_t ), 1, fpr, &enc_param ) != 1 ) {
            XPRINT_ERR( 1794, XERR_IO_MSG );
            return XERR_IO;
        }

        xrn_crc32( ( uint8_t * ) & pkey_local.state[i], sizeof( xnum_t ), &crc32_local );

    }

    if ( xrn_fread_decoder( &crc32_stored, sizeof( crc32_stored ), 1, fpr, &enc_param ) != 1 ) {
        XPRINT_ERR( 1795, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( crc32_stored != crc32_local ) {
        XPRINT_ERR( 1796, XERR_CRC_MSG );
        return XERR_CRC;
    }

    *pkey = pkey_local;
    *settings = settings_local;

    return final_ret;

}

int xrn_dump_binomial_key( xbinomial_key_t bk, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1797, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1798, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_binomial_key;
    ret = dump_two_xnums( bk.start, bk.end, type, settings.crc_bytes, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 661, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_dump_binomial_commitment( xbinomial_commitment_t bc, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1801, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1802, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_binomial_commitment;
    ret = dump_two_xnums( bc.start, bc.end, type, settings.crc_bytes, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1800, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_dump_monomial_commitment( xmonomial_commitment_t mcommitment, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int final_ret, ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1805, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1806, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    ret = xrn_check_sparsity( mcommitment.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 1820, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    type = c_monomial_commitment;
    ret = dump_xnum( mcommitment.distance, type, settings.crc_bytes, settings.state_size, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 828, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_dump_monomial_response( xmonomial_response_t mresponse, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1809, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1810, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_monomial_response;
    ret = dump_xnum( mresponse.distance, type, settings.crc_bytes, settings.state_size, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1808, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_dump_monomial_proof( xmonomial_proof_t mproof, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1813, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1814, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_monomial_proof;
    ret = dump_xnum( mproof.distance, type, settings.crc_bytes, settings.state_size, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1816, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_dump_monomial_key( xmonomial_key_t mkey, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1817, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1818, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( mkey.distance );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 830, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    type = c_monomial_key;
    ret = dump_xnum( mkey.distance, type, settings.crc_bytes, settings.state_size, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1821, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_load_binomial_commitment( xbinomial_commitment_t * bc, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    xnum_t a, b;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( bc == NULL ) ) {
        XPRINT_ERR( 1822, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;
    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1823, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_binomial_commitment;
    ret = load_two_xnums( &a, &b, &crc_bytes, &state_size, &type, exp_type, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1825, XERR_GENERAL_MSG );
        return ret;
    }

    bc->start = a;
    bc->end = b;
    *settings = settings_local;
    return final_ret;
}

int xrn_load_binomial_key( xbinomial_key_t * bk, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    xnum_t a, b;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( bk == NULL ) ) {
        XPRINT_ERR( 1826, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1827, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_binomial_key;
    ret = load_two_xnums( &a, &b, &crc_bytes, &state_size, &type, exp_type, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1122, XERR_GENERAL_MSG );
        return ret;
    }

    bk->start = a;
    bk->end = b;
    *settings = settings_local;

    return ret;
}

int xrn_load_monomial_response( xmonomial_response_t * mr, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    int ret;
    int final_ret;
    xnum_t tmp;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( mr == NULL ) ) {
        XPRINT_ERR( 1830, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1831, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_monomial_response;
    ret = load_xnum( &tmp, &crc_bytes, &type, exp_type, &state_size, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1833, XERR_GENERAL_MSG );
        return ret;
    }

    mr->distance = tmp;
    *settings = settings_local;

    return final_ret;

}

int xrn_load_monomial_proof( xmonomial_proof_t * mp, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    int ret;
    int final_ret;
    xnum_t tmp;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( mp == NULL ) ) {
        XPRINT_ERR( 1834, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1835, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_monomial_proof;
    ret = load_xnum( &tmp, &crc_bytes, &type, exp_type, &state_size, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1837, XERR_GENERAL_MSG );
        return ret;
    }

    mp->distance = tmp;
    *settings = settings_local;

    return final_ret;

}

int xrn_load_monomial_commitment( xmonomial_commitment_t * mc, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    int ret;
    int final_ret;
    xnum_t tmp;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( mc == NULL ) ) {
        XPRINT_ERR( 1838, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1839, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_monomial_commitment;
    ret = load_xnum( &tmp, &crc_bytes, &type, exp_type, &state_size, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1841, XERR_GENERAL_MSG );
        return ret;
    }

    // check sparsity

    ret = xrn_check_sparsity( tmp );
    if ( ret == XERR_SPARSE_MKEY ) {
        XPRINT_ERR( 829, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    mc->distance = tmp;
    *settings = settings_local;

    return final_ret;
}

int xrn_load_monomial_key( xmonomial_key_t * mkey, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    int ret;
    int final_ret;
    xnum_t tmp;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( mkey == NULL ) ) {
        XPRINT_ERR( 1842, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1843, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_monomial_key;
    ret = load_xnum( &tmp, &crc_bytes, &type, exp_type, &state_size, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1845, XERR_GENERAL_MSG );
        return ret;
    }

    // check monomial key sparsity

    ret = xrn_check_sparsity( tmp );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1846, XERR_SPARSE_MKEY_MSG );
        return ret;
    }

    mkey->distance = tmp;
    *settings = settings_local;

    return final_ret;

}

int xrn_dump_signature_asy( xsignature_asy_t sig, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1847, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1848, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_signature_asy;
    ret = dump_two_xnums( sig.hint, sig.proof, type, settings.crc_bytes, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1851, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_dump_signature_sym( xsignature_sym_t sig, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1852, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1853, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_signature_sym;
    ret = dump_two_xnums( sig.hint, sig.proof, type, settings.crc_bytes, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1855, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_load_signature_asy( xsignature_asy_t * sig, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_crypto_extra_settings_t settings_local;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    xnum_t a, b;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( sig == NULL ) || ( settings == NULL ) ) {
        XPRINT_ERR( 1856, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1857, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_signature_asy;
    ret =
        load_two_xnums( &a, &b, &settings_local.crc_bytes,
                        &settings_local.state_size, &type, exp_type, fp, *settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1859, XERR_GENERAL_MSG );
        return ret;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1860, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    sig->hint = a;
    sig->proof = b;
    settings->state_size = settings_local.state_size;

    return final_ret;
}

int xrn_load_signature_sym( xsignature_sym_t * sig, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_crypto_extra_settings_t settings_local;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    xnum_t a, b;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( sig == NULL ) || ( settings == NULL ) ) {
        XPRINT_ERR( 1861, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1862, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_signature_sym;
    ret =
        load_two_xnums( &a, &b, &settings_local.crc_bytes,
                        &settings_local.state_size, &type, exp_type, fp, *settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1864, XERR_GENERAL_MSG );
        return ret;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1865, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    sig->hint = a;
    sig->proof = b;
    settings->state_size = settings_local.state_size;

    return final_ret;
}

int xrn_dump_start_point( xstart_point_t start, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1866, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1867, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_start;
    ret = dump_xnum( start.start, type, settings.crc_bytes, settings.state_size, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1869, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_load_start_point( xstart_point_t * start, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    int ret;
    int final_ret;
    xnum_t tmp;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( start == NULL ) ) {
        XPRINT_ERR( 1870, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;
    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1871, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_start;
    ret = load_xnum( &tmp, &crc_bytes, &type, exp_type, &state_size, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1873, XERR_GENERAL_MSG );
        return ret;
    }

    start->start = tmp;
    *settings = settings_local;

    return final_ret;
}

int xrn_dump_hash( xhash_t hash, FILE * fp, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    int ret;
    int final_ret;
    xrn_lib_xtype_t type;

    final_ret = XSUCCESS;

    if ( fp == NULL ) {
        XPRINT_ERR( 1874, XERR_NULL_MSG );
        return XERR_NULL;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 1875, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    type = c_hash;
    ret = dump_xnum( hash.value, type, settings.crc_bytes, settings.state_size, fp, settings );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1877, XERR_GENERAL_MSG );
        return ret;
    }

    return final_ret;
}

int xrn_load_hash( xhash_t * hash, FILE * fp, xrn_crypto_extra_settings_t * settings
 )
{
    XPRINT_DEB(  );

    uint8_t crc_bytes;
    uint8_t state_size;
    xrn_lib_xtype_t type;
    xrn_lib_xtype_t exp_type;
    int ret;
    int final_ret;
    xnum_t tmp;
    xrn_crypto_extra_settings_t settings_local;

    final_ret = XSUCCESS;

    if ( ( fp == NULL ) || ( hash == NULL ) || ( settings == NULL ) ) {
        XPRINT_ERR( 1878, XERR_NULL_MSG );
        return XERR_NULL;
    }

    settings_local = *settings;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1879, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    exp_type = c_hash;
    ret = load_xnum( &tmp, &crc_bytes, &type, exp_type, &state_size, fp, settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1881, XERR_GENERAL_MSG );
        return ret;
    }

    ret = xrn_load_default_settings( &settings_local );

    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1882, XERR_GENERAL_MSG );
        return ret;
    }

    settings_local.state_size = state_size;

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings_local ) ) {
        XPRINT_ERR( 1883, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    settings->state_size = state_size;
    hash->value = tmp;

    return final_ret;

}

int xrn_convert_type_wrapper( FILE * fpi, FILE * fpo, xrn_lib_xtype_t in_type, xrn_lib_xtype_t out_type,
                              xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xstart_point_t start_point;
    xrn_point_t point;
    xhash_t hash;
    xmonomial_key_t mkey;
    xbinomial_key_t bkey;
    xmonomial_commitment_t mcommitment;
    xbinomial_commitment_t bcommitment;
    xmonomial_response_t mresponse;
    xmonomial_proof_t mproof;
    xcertificate_asy_t certasy;
    xcertificate_sym_t certsym;
    xsignature_asy_t sigasy;
    xsignature_sym_t sigsym;
    xmonovalent_key_t monovalent_key;
    int ret, final_ret;

    final_ret = XSUCCESS;

    if ( ( in_type == c_start ) && ( out_type == c_point ) ) {

        ret = xrn_load_start_point( &start_point, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1884, XERR_GENERAL_MSG );
            return ret;
        }

        point.point = start_point.start;

        ret = xrn_dump_point( point, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1885, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_binomial_key ) && ( in_type == c_signature_sym ) ) {

        ret = xrn_load_signature_sym( &sigsym, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1179, XERR_GENERAL_MSG );
            return ret;
        }

        bkey.start = sigsym.hint;
        bkey.end = sigsym.proof;

        ret = xrn_dump_binomial_key( bkey, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 790, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_signature_sym ) && ( in_type == c_binomial_key ) ) {

        ret = xrn_load_binomial_key( &bkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1180, XERR_GENERAL_MSG );
            return ret;
        }

        sigsym.hint = bkey.start;
        sigsym.proof = bkey.end;

        ret = xrn_dump_signature_sym( sigsym, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1167, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_binomial_key ) && ( in_type == c_signature_asy ) ) {
        ret = xrn_load_signature_asy( &sigasy, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1182, XERR_GENERAL_MSG );
            return ret;
        }

        bkey.start = sigasy.hint;
        bkey.end = sigasy.proof;

        ret = xrn_dump_binomial_key( bkey, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1168, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_signature_asy ) && ( in_type == c_binomial_key ) ) {

        ret = xrn_load_binomial_key( &bkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1183, XERR_GENERAL_MSG );
            return ret;
        }

        sigasy.hint = bkey.start;
        sigasy.proof = bkey.end;

        ret = xrn_dump_signature_asy( sigasy, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1178, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_monovalent_key ) && ( in_type == c_certificate_sym ) ) {

        ret = xrn_load_certificate_sym( &certsym, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 762, XERR_GENERAL_MSG );
            return ret;
        }

        monovalent_key = certsym.monovalent_key;

        ret = xrn_dump_monovalent_key( monovalent_key, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 761, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_binomial_key ) && ( in_type == c_certificate_asy ) ) {

        ret = xrn_load_certificate_asy( &certasy, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 764, XERR_GENERAL_MSG );
            return ret;
        }

        bkey = certasy.binomial_key;

        ret = xrn_dump_binomial_key( bkey, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 765, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_start ) && ( in_type == c_point ) ) {

        ret = xrn_load_point( &point, fpi, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1886, XERR_GENERAL_MSG );
            return ret;
        }

        start_point.start = point.point;

        ret = xrn_dump_start_point( start_point, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1887, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_start ) && ( out_type == c_monomial_key ) ) {

        ret = xrn_load_start_point( &start_point, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1888, XERR_GENERAL_MSG );
            return ret;
        }

        mkey.distance = start_point.start;

        ret = xrn_dump_monomial_key( mkey, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1889, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_start ) && ( in_type == c_monomial_key ) ) {

        ret = xrn_load_monomial_key( &mkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1890, XERR_GENERAL_MSG );
            return ret;
        }

        start_point.start = mkey.distance;
        ret = xrn_dump_start_point( start_point, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1891, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_start ) && ( in_type == c_hash ) ) {

        ret = xrn_load_hash( &hash, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1892, XERR_GENERAL_MSG );
            return ret;
        }

        start_point.start = hash.value;

        ret = xrn_dump_start_point( start_point, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1893, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_point ) && ( out_type == c_monomial_key ) ) {

        ret = xrn_load_point( &point, fpi, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1894, XERR_GENERAL_MSG );
            return ret;
        }

        mkey.distance = point.point;

        ret = xrn_dump_monomial_key( mkey, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1895, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_point ) && ( in_type == c_monomial_key ) ) {

        ret = xrn_load_monomial_key( &mkey, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1896, XERR_GENERAL_MSG );
            return ret;
        }

        point.point = mkey.distance;

        ret = xrn_dump_point( point, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1897, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_point ) && ( in_type == c_hash ) ) {

        ret = xrn_load_hash( &hash, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1898, XERR_GENERAL_MSG );
            return ret;
        }

        point.point = hash.value;

        ret = xrn_dump_point( point, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1899, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( out_type == c_monomial_key ) && ( in_type == c_hash ) ) {

        ret = xrn_load_hash( &hash, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1900, XERR_GENERAL_MSG );
            return ret;
        }

        mkey.distance = hash.value;
        while ( XERR_SPARSE_MKEY == xrn_check_sparsity( mkey.distance ) ) {
            xrn_add_nums( hash.value, hash.value, 1, &mkey.distance );
        }

        ret = xrn_dump_monomial_key( mkey, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1901, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_monomial_commitment ) && ( out_type == c_monomial_key ) ) {

        ret = xrn_load_monomial_commitment( &mcommitment, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1902, XERR_GENERAL_MSG );
            return ret;
        }

        mkey.distance = mcommitment.distance;

        ret = xrn_dump_monomial_key( mkey, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1903, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_monomial_key ) && ( out_type == c_monomial_commitment ) ) {

        ret = xrn_load_monomial_key( &mkey, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1904, XERR_GENERAL_MSG );
            return ret;
        }

        mcommitment.distance = mkey.distance;

        ret = xrn_dump_monomial_commitment( mcommitment, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1905, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_monomial_response ) && ( out_type == c_monomial_key ) ) {

        ret = xrn_load_monomial_response( &mresponse, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1906, XERR_GENERAL_MSG );
            return ret;
        }

        mkey.distance = mresponse.distance;
        ret = xrn_dump_monomial_key( mkey, fpo, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1907, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_monomial_key ) && ( out_type == c_monomial_response ) ) {

        ret = xrn_load_monomial_key( &mkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1908, XERR_GENERAL_MSG );
            return ret;
        }

        mresponse.distance = mkey.distance;
        ret = xrn_dump_monomial_response( mresponse, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1909, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_monomial_proof ) && ( out_type == c_monomial_key ) ) {

        ret = xrn_load_monomial_proof( &mproof, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1910, XERR_GENERAL_MSG );
            return ret;
        }

        mkey.distance = mproof.distance;
        ret = xrn_dump_monomial_key( mkey, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1911, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_monomial_key ) && ( out_type == c_monomial_proof ) ) {

        ret = xrn_load_monomial_key( &mkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1912, XERR_GENERAL_MSG );
            return ret;
        }

        mproof.distance = mkey.distance;

        ret = xrn_dump_monomial_proof( mproof, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1913, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_binomial_commitment ) && ( out_type == c_binomial_key ) ) {

        ret = xrn_load_binomial_commitment( &bcommitment, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1914, XERR_GENERAL_MSG );
            return ret;
        }

        bkey.start = bcommitment.start;
        bkey.end = bcommitment.end;

        ret = xrn_dump_binomial_key( bkey, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1915, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_binomial_key ) && ( out_type == c_binomial_commitment ) ) {

        ret = xrn_load_binomial_key( &bkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1916, XERR_GENERAL_MSG );
            return ret;
        }

        bcommitment.start = bkey.start;
        bcommitment.end = bkey.end;

        ret = xrn_dump_binomial_commitment( bcommitment, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 1917, XERR_GENERAL_MSG );
            return ret;
        }

    } else if ( ( in_type == c_binomial_key ) && ( out_type == c_start ) ) {

        ret = xrn_load_binomial_key( &bkey, fpi, &settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 659, XERR_GENERAL_MSG );
            return ret;
        }

        start_point.start = bkey.start;

        ret = xrn_dump_start_point( start_point, fpo, settings );

        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            XPRINT_ERR( 660, XERR_GENERAL_MSG );
            return ret;
        }

    } else {
        XPRINT_ERR( 1918, XERR_TYPE_MSG );
        return XERR_TYPE;
    }

    return final_ret;
}

int xrn_name_2_type( char *function_str, xrn_lib_xtype_t * type, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    if ( ( function_str == NULL ) || ( type == NULL ) ) {
        XPRINT_ERR( 1945, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( ( !strcmp( function_str, "xrn_decrypt_asymmetric_bytes_wrapper" ) )
         || ( !strcmp( function_str, "xrn_encrypt_asymmetric_bytes_wrapper" ) )
         || ( !strcmp( function_str, "xrn_encrypt_asymmetric_bytes" ) )
         || ( !strcmp( function_str, "xrn_decrypt_asymmetric_bytes" ) ) ) {

        *type = c_asy_encryption;

    } else if ( ( !strcmp( function_str, "xrn_encrypt_symmetric_bytes" ) )
                || ( !strcmp( function_str, "xrn_encrypt_symmetric_bytes_wrapper" ) )
                || ( !strcmp( function_str, "xrn_decrypt_symmetric_bytes_wrapper" ) )
                || ( !strcmp( function_str, "xrn_decrypt_symmetric_bytes" ) ) ) {

        *type = c_sym_encryption;

    } else {
        XPRINT_ERR( 1950, XERR_TYPE_MSG );
        return XERR_TYPE;
    }

    return XSUCCESS;

}

int xrn_name_2_types( char *function_str, xrn_lib_xtype_t * challenge_type, xrn_lib_xtype_t * solution_type,
                      xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    if ( function_str == NULL ) {
        XPRINT_ERR( 1951, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( ( !strcmp( function_str, "xrn_split_bytes_wrapper" ) )
         || ( !strcmp( function_str, "xrn_split_bytes" ) )
         || ( !strcmp( function_str, "xrn_join_bytes_wrapper" ) )
         || ( !strcmp( function_str, "xrn_join_bytes" ) ) ) {
        *challenge_type = c_challenge;
        *solution_type = c_solution;

    } else {
        XPRINT_ERR( 1954, XERR_TYPE_MSG );
        return XERR_TYPE;
    }

    return XSUCCESS;

}

int xrn_print_metadata( FILE * fpi, xrn_crypto_extra_settings_t settings
 )
{
    XPRINT_DEB(  );

    xrn_crypto_lib_header_t header, header2;
    uint64_t file_size;
    char buffer[256];
    char big_buffer[8192];
    int i, j, final_ret, ret;

    xgenesis_base_t xgenesis_base;
    xrn_vector_t xvector;
    xrn_matrix_compressed_t xmatrixc;
    xrn_matrix_t xmatrix;
    xrn_base_t xbase;

    xmonomial_key_t monomial_key;
    xbinomial_key_t binomial_key;
    xstart_point_t start_point;
    xmonovalent_key_t monovalent_key;
    xpolyvalent_key_t polyvalent_key;
    xpolyvalent_proof_t polyvalent_proof;
    xrn_point_t pktpoint;
    xhash_t hash;
    xsignature_asy_t signature_asy;
    xsignature_sym_t signature_sym;
    xring_signature_t ring_signature;
    xcertificate_asy_t certificate_asy;
    xcertificate_sym_t certificate_sym;
    xbinomial_commitment_t binomial_commitment;
    xmonomial_commitment_t monomial_commitment;
    xmonomial_response_t monomial_response;
    xmonomial_proof_t monomial_proof;
    uint16_t crc16;
    uint8_t crc_bytes_local;
    uint8_t filetype;
    uint32_t magic_number;
    header_block_t header_block;
    char tabs[5];
    int nbits;

    uint32_t crc32;
    uint32_t magic_num_tmp;
    xrn_encoding_param_t local_param;
    xrn_encoding_param_t rnd_param;
    xrn_encoding_param_t rnd_param_perm;

    xrn_encoding_param_t enc_param;
    uint16_t permutations[XRN_ENCODING_PERMUTATION_LEN] = XRN_ENCODING_PERMUTATION;

    if ( ( xlog.not_fp == NULL ) || ( fpi == NULL ) ) {
        XPRINT_ERR( 734, XERR_NULL_MSG );
        return XERR_NULL;
    }

    if ( xlog.not_en == 0 ) {
        XPRINT_ERR( 731, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    // check extra settings

    if ( XSUCCESS != check_crypto_extra_settings_value( settings ) ) {
        XPRINT_ERR( 627, XERR_SETTINGS_MSG );
        return XERR_SETTINGS;
    }

    final_ret = XSUCCESS;

    strncpy( tabs, "   ", 4 );

    // initialize encoding decoding param
    ret = xrn_initialize_encoding_parameters( &enc_param, settings.encoding_settings.i_settings );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        XPRINT_ERR( 1956, XERR_GENERAL_MSG );
        return ret;
    }

    // check if checksum-dump or if block file

    // block file

    if ( fread( &magic_number, sizeof( magic_number ), 1, fpi ) != 1 ) {
        XPRINT_ERR( 1957, XERR_IO_MSG );
        return XERR_IO;
    }

    if ( magic_number == XRN_MAGIC_NUMBER_BLOCK ) {

        fprintf( xlog.not_fp, "{\n%s\"message_type\" : \"block\",\n", tabs );

        if ( fread( &header_block, sizeof( header_block ), 1, fpi ) != 1 ) {
            XPRINT_ERR( 691, XERR_IO_MSG );
            return XERR_IO;
        }

        fprintf( xlog.not_fp, "\n%s\"header_block\" : {\n%s%s\"magic_number\" : %u,\n", tabs, tabs, tabs,
                 header_block.magic_number );
        fprintf( xlog.not_fp, "%s%s\"tag\" : %u,\n", tabs, tabs, header_block.tag );
        fprintf( xlog.not_fp, "%s%s\"offset\" : %lu,\n", tabs, tabs, header_block.offset );
        fprintf( xlog.not_fp, "%s%s\"length\" : %lu,\n", tabs, tabs, header_block.length );
        fprintf( xlog.not_fp, "%s%s\"total_length\" : %lu,\n", tabs, tabs, header_block.total_length );
        fprintf( xlog.not_fp, "%s%s\"crc8\" : %u\n%s}\n}\n", tabs, tabs, header_block.crc8, tabs );

        return XSUCCESS;

    } else {                    // check if the file is an encoding parameter file

        // Determine the file size
        if ( 0 != fseek( fpi, 0, SEEK_END ) ) {
            XPRINT_ERR( 620, XERR_IO_MSG );
            return XERR_IO;
        }

        file_size = ( uint64_t ) ftell( fpi );

        if ( 0 != fseek( fpi, 0, SEEK_SET ) ) {
            XPRINT_ERR( 622, XERR_IO_MSG );
            return XERR_IO;
        }

        if ( file_size > XRN_ENCODING_PERMUTATION_LEN * 2 + 1 ) {

            if ( 1 != fread( &magic_number, sizeof( uint32_t ), 1, fpi ) ) {
                XPRINT_ERR( 623, XERR_IO_MSG );
                return XERR_IO;
            }

            for ( i = 0; i < sizeof( local_param ); i++ ) {
                ( ( uint8_t * ) & local_param )[i] = 0;
            }

            final_ret = XSUCCESS;

            // get encrypted encoding param
            for ( i = 0; i < 256; i++ ) {

                if ( 1 != fread( &local_param.table[i], sizeof( uint8_t ), 1, fpi ) ) {
                    XPRINT_ERR( 624, XERR_IO_MSG );
                    return XERR_IO;
                }

            }

            for ( i = 0; i < 4; i++ ) {
                if ( 1 != fread( &local_param.prng_state[i], sizeof( uint64_t ), 1, fpi ) ) {
                    XPRINT_ERR( 625, XERR_IO_MSG );
                    return XERR_IO;

                }

            }

            // get random encoding param
            for ( i = 0; i < 256; i++ ) {

                if ( 1 != fread( &rnd_param.table[i], sizeof( uint8_t ), 1, fpi ) ) {
                    XPRINT_ERR( 626, XERR_IO_MSG );
                    return XERR_IO;
                }

            }

            for ( i = 0; i < 4; i++ ) {
                if ( 1 != fread( &rnd_param.prng_state[i], sizeof( uint64_t ), 1, fpi ) ) {
                    XPRINT_ERR( 628, XERR_IO_MSG );
                    return XERR_IO;

                }

            }

            // permute bytes
            for ( i = 0; i < XRN_ENCODING_PERMUTATION_LEN; i++ ) {
                ( ( uint8_t * ) & rnd_param_perm.table[0] )[permutations[i]] =
                    ( ( uint8_t * ) & rnd_param.table[0] )[i];
            }

            // decrypt encoding param
            for ( i = 0; i < 256; i++ ) {
                local_param.table[i] = local_param.table[i] ^ rnd_param_perm.table[i];

            }

            for ( i = 0; i < 4; i++ ) {
                local_param.prng_state[i] = local_param.prng_state[i] ^ rnd_param_perm.prng_state[i];

            }

            crc32 = 0xffffffff;
            magic_num_tmp = XRN_ENC_MAGIC_NUM;
            xrn_crc32( ( uint8_t * ) & magic_num_tmp, sizeof( uint32_t ), &crc32 );
            xrn_crc32( ( uint8_t * ) & local_param.table[0], sizeof( uint8_t ) * 256, &crc32 );
            xrn_crc32( ( uint8_t * ) & local_param.prng_state[0], sizeof( uint64_t ) * 1, &crc32 );
            xrn_crc32( ( uint8_t * ) & local_param.prng_state[1], sizeof( uint64_t ) * 1, &crc32 );
            xrn_crc32( ( uint8_t * ) & local_param.prng_state[2], sizeof( uint64_t ) * 1, &crc32 );
            xrn_crc32( ( uint8_t * ) & local_param.prng_state[3], sizeof( uint64_t ) * 1, &crc32 );

            if ( magic_number == crc32 ) {

                ret = xrn_check_encoding_parameters( local_param );
                final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
                if ( final_ret != XERR_GENERAL ) {

                    fprintf( xlog.not_fp, "{\n%s\"message_type\" : \"encoding_parameters\",\n", tabs );
                    fprintf( xlog.not_fp, "%s\"encoding_table\" : [ ", tabs );
                    for ( i = 0; i < 256; i++ ) {
                        if ( i != 255 ) {
                            fprintf( xlog.not_fp, "%3d, ", local_param.table[i] );
                        } else {
                            fprintf( xlog.not_fp, "%3d ],\n", local_param.table[i] );
                        }

                    }

                    fprintf( xlog.not_fp, "%s\"pseurdo_random_number_generator_state\" : [ ", tabs );
                    for ( i = 0; i < 4; i++ ) {
                        if ( i != 3 ) {
                            fprintf( xlog.not_fp, "%lu, ", local_param.prng_state[i] );
                        } else {
                            fprintf( xlog.not_fp, "%lu ]\n}\n", local_param.prng_state[i] );
                        }

                    }

                    return XSUCCESS;
                }

            }

        }

    }

    rewind( fpi );

    // print header
    if ( xrn_fread_decoder( &header, sizeof( xrn_crypto_lib_header_t ), 1, fpi, &enc_param ) != 1 ) {

        rewind( fpi );
        XPRINT_ERR( 693, XERR_IO_MSG );
        return XERR_IO;
    }

    final_ret = XSUCCESS;

    header2 = header;
    header2.crc16 = 0xffff;
    crc16 = 0xffff;
    xrn_crc16( ( uint8_t * ) & header2, sizeof( header2 ) - 1, &crc16 );
    header2.crc16 = crc16;

    if ( header2.crc16 != header.crc16 ) {
        rewind( fpi );
        XPRINT_ERR( 1958, XERR_CRC_MSG );
        return XERR_CRC;
    }

    fprintf( xlog.not_fp,
             "{\n%s\"message_type\" : \"data_structure\",\n%s\"header\" : {\n%s%s\"magic_number\" : %u,\n",
             tabs, tabs, tabs, tabs, header.magic_number );
    fprintf( xlog.not_fp, "%s%s\"version\" : %u,\n", tabs, tabs, header.version );
    fprintf( xlog.not_fp, "%s%s\"reserved_0\" : %u,\n", tabs, tabs, header.reserved_0 );
    fprintf( xlog.not_fp, "%s%s\"reserved_1\" : %u,\n", tabs, tabs, header.reserved_1 );
    fprintf( xlog.not_fp, "%s%s\"state_size\" : %u,\n", tabs, tabs, header.state_size );

    filetype = ( uint8_t ) ( header.type >> 3 );

    ret = xrn_convert_libtype_to_string( filetype, buffer, 256 );
    final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
    if ( final_ret == XERR_GENERAL ) {
        rewind( fpi );
        XPRINT_ERR( 1959, XERR_GENERAL_MSG );
        return ( ret );
    }

    fprintf( xlog.not_fp, "%s%s\"type\" : \"%s\",\n", tabs, tabs, buffer );

    xrn_load_sub_type( header.type, &crc_bytes_local, &nbits );

    fprintf( xlog.not_fp, "%s%s\"nbits\" : %u,\n", tabs, tabs, nbits );
    if ( crc_bytes_local == 0 ) {
        crc_bytes_local = 8;
    } else if ( crc_bytes_local == 1 ) {
        crc_bytes_local = 16;
    } else if ( crc_bytes_local == 2 ) {
        crc_bytes_local = 32;
    } else if ( crc_bytes_local == 3 ) {
        crc_bytes_local = 64;
    }

    fprintf( xlog.not_fp, "%s%s\"crc_bytes\" : %u,\n", tabs, tabs, crc_bytes_local );

    if ( ( filetype == c_asy_encryption ) || ( filetype == c_sym_encryption ) ) {
        if ( header.magic_number != XRN_PERMUTATION_NUMBER ) {
            XPRINT_ERR( 112, XERR_IO_MSG );
            return XERR_IO;
        }

    } else {
        if ( header.magic_number != XRN_PERMUTATION_NUMBER ) {
            XPRINT_ERR( 604, XERR_IO_MSG );
            return XERR_IO;
        }

    }

    // print data

    rewind( fpi );

    if ( filetype == c_genesis ) {
        ret = xrn_load_genesis_base( fpi, &xgenesis_base, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1960, XERR_GENERAL_MSG );
            return ( ret );
        }

        base64_encode( ( char * ) &xgenesis_base.base_vector,
                       sizeof( xgenesis_base.base_vector ), big_buffer );
        fprintf( xlog.not_fp, "%s\"base_vector\" : \"%s\"\n}\n", tabs, big_buffer );

    }

    if ( filetype == c_base ) {
        ret = xrn_load_base( fpi, &xbase, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 682, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( xbase.sign_vector, buffer );
        fprintf( xlog.not_fp, "%s\"sign_vector\" : \"%s\", \n", tabs, buffer );

        fprintf( xlog.not_fp, "%s\"base_matrix\" : [ \n", tabs );

        for ( i = 0; i < XNBITS; i++ ) {
            xrn_bin_to_base64( xbase.base_matrix.xmat[i], buffer );
            if ( i < XNBITS - 1 ) {
                fprintf( xlog.not_fp, "%s%s\"%s\",\n", tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s\"%s\" ]\n}\n", tabs, tabs, buffer );
            }

        }

    }

    if ( filetype == c_vector ) {
        ret = xrn_load_vector( fpi, &xvector, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 683, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( xvector.entry_point, buffer );
        fprintf( xlog.not_fp, "%s\"entry_point\" : \"%s\", \n", tabs, buffer );

        fprintf( xlog.not_fp, "%s\"base\" : { \n", tabs );

        xrn_bin_to_base64( xvector.xbase.sign_vector, buffer );
        fprintf( xlog.not_fp, "%s%s\"sign_vector\" : \"%s\", \n", tabs, tabs, buffer );

        fprintf( xlog.not_fp, "%s%s\"base_matrix\" : [ \n", tabs, tabs );

        for ( i = 0; i < XNBITS; i++ ) {
            xrn_bin_to_base64( xvector.xbase.base_matrix.xmat[i], buffer );
            if ( i < XNBITS - 1 ) {
                fprintf( xlog.not_fp, "%s%s%s\"%s\",\n", tabs, tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s%s\"%s\" ]\n%s}\n}\n", tabs, tabs, tabs, buffer, tabs );
            }

        }

    }

    if ( filetype == c_matrix ) {
        ret = xrn_load_matrix( fpi, &xmatrix, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 687, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( xmatrix.xrn_dead_code, buffer );
        fprintf( xlog.not_fp, "%s\"dead_code\" : \"%s\", \n", tabs, buffer );

        fprintf( xlog.not_fp, "%s\"vectors\" : [\n", tabs );

        for ( j = 0; j < XNBITS; j++ ) {

            xrn_bin_to_base64( xmatrix.xvector[j].entry_point, buffer );
            fprintf( xlog.not_fp, "%s%s{\n%s%s%s\"entry_point\" : \"%s\", \n", tabs, tabs, tabs, tabs, tabs,
                     buffer );

            fprintf( xlog.not_fp, "%s%s%s\"base\" : { \n", tabs, tabs, tabs );

            xrn_bin_to_base64( xmatrix.xvector[j].xbase.sign_vector, buffer );
            fprintf( xlog.not_fp, "%s%s%s%s\"sign_vector\" : \"%s\", \n", tabs, tabs, tabs, tabs, buffer );

            fprintf( xlog.not_fp, "%s%s%s%s\"base_matrix\" : [ \n", tabs, tabs, tabs, tabs );

            for ( i = 0; i < XNBITS; i++ ) {
                xrn_bin_to_base64( xmatrix.xvector[j].xbase.base_matrix.xmat[i], buffer );
                if ( i < XNBITS - 1 ) {
                    fprintf( xlog.not_fp, "%s%s%s%s%s\"%s\",\n", tabs, tabs, tabs, tabs, tabs, buffer );
                } else {
                    if ( j < XNBITS - 1 ) {
                        fprintf( xlog.not_fp, "%s%s%s%s%s\"%s\" ]\n%s%s%s}\n%s%s},\n", tabs, tabs, tabs, tabs,
                                 tabs, buffer, tabs, tabs, tabs, tabs, tabs );
                    } else {
                        fprintf( xlog.not_fp, "%s%s%s%s%s\"%s\" ]\n%s%s%s}\n%s%s}\n%s]\n}\n", tabs, tabs,
                                 tabs, tabs, tabs, buffer, tabs, tabs, tabs, tabs, tabs, tabs );
                    }

                }

            }

        }

    }

    if ( filetype == c_matrix_compressed ) {
        ret = xrn_load_matrix_compressed( fpi, &xmatrixc, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 686, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( xmatrixc.change_of_sign, buffer );
        fprintf( xlog.not_fp, "%s\"change_of_sign\" : \"%s\", \n", tabs, buffer );
        xrn_bin_to_base64( xmatrixc.change_of_base, buffer );
        fprintf( xlog.not_fp, "%s\"change_of_base\" : \"%s\", \n", tabs, buffer );

        base64_encode( ( char * ) &xmatrixc.xgenesis_base.base_vector,
                       sizeof( xmatrixc.xgenesis_base.base_vector ), big_buffer );
        fprintf( xlog.not_fp, "%s\"base_vector\" : \"%s\"\n}\n", tabs, big_buffer );

    }

    if ( filetype == c_start ) {

        ret = xrn_load_start_point( &start_point, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 688, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( start_point.start, buffer );
        fprintf( xlog.not_fp, "%s\"start\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_monomial_key ) {

        ret = xrn_load_monomial_key( &monomial_key, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1961, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( monomial_key.distance, buffer );
        fprintf( xlog.not_fp, "%s\"distance\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_binomial_key ) {

        ret = xrn_load_binomial_key( &binomial_key, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1962, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( binomial_key.start, buffer );
        fprintf( xlog.not_fp, "%s\"start\" : \"%s\",\n", tabs, buffer );
        xrn_bin_to_base64( binomial_key.end, buffer );
        fprintf( xlog.not_fp, "%s\"end\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_monovalent_key ) {
        monovalent_key.start_timestamp = 0;
        monovalent_key.end_timestamp = 0;
        ret = xrn_load_monovalent_key( &monovalent_key, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1963, XERR_GENERAL_MSG );
            return ( ret );
        }

        fprintf( xlog.not_fp, "%s\"start_timestamp\" : %ld,\n", tabs, monovalent_key.start_timestamp );
        fprintf( xlog.not_fp, "%s\"end_timestamp\" : %ld,\n", tabs, monovalent_key.end_timestamp );
        fprintf( xlog.not_fp, "%s\"points\" : [\n", tabs );
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
            xrn_bin_to_base64( monovalent_key.state[i], buffer );
            if ( i < XRN_STATE_KEY_SIZE - 1 ) {
                fprintf( xlog.not_fp, "%s%s\"%s\",\n", tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s\"%s\" ]\n}\n", tabs, tabs, buffer );
            }

        }

    }

    if ( filetype == c_polyvalent_key ) {
        ret = xrn_load_polyvalent_key( &polyvalent_key, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1964, XERR_GENERAL_MSG );
            return ( ret );
        }

        fprintf( xlog.not_fp, "%s\"points\" : [\n", tabs );
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
            xrn_bin_to_base64( polyvalent_key.state[i], buffer );
            if ( i < XRN_STATE_KEY_SIZE - 1 ) {
                fprintf( xlog.not_fp, "%s%s\"%s\",\n", tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s\"%s\" ]\n}\n", tabs, tabs, buffer );
            }

        }

    }

    if ( filetype == c_polyvalent_proof ) {
        ret = xrn_load_polyvalent_proof( &polyvalent_proof, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1965, XERR_GENERAL_MSG );
            return ( ret );
        }

        fprintf( xlog.not_fp, "%s\"points\" : [\n", tabs );
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
            xrn_bin_to_base64( polyvalent_proof.state[i], buffer );
            if ( i < XRN_STATE_KEY_SIZE - 1 ) {
                fprintf( xlog.not_fp, "%s%s\"%s\",\n", tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s\"%s\" ]\n}\n", tabs, tabs, buffer );
            }

        }

    }

    if ( filetype == c_point ) {

        ret = xrn_load_point( &pktpoint, fpi, settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1966, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( pktpoint.point, buffer );
        fprintf( xlog.not_fp, "%s\"point\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_hash ) {

        ret = xrn_load_hash( &hash, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1967, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( hash.value, buffer );
        fprintf( xlog.not_fp, "%s\"value\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_signature_sym ) {

        ret = xrn_load_signature_sym( &signature_sym, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1968, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( signature_sym.hint, buffer );
        fprintf( xlog.not_fp, "%s\"hint\" : \"%s\",\n", tabs, buffer );
        xrn_bin_to_base64( signature_sym.proof, buffer );
        fprintf( xlog.not_fp, "%s\"proof\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_signature_asy ) {

        ret = xrn_load_signature_asy( &signature_asy, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1969, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( signature_asy.hint, buffer );
        fprintf( xlog.not_fp, "%s\"hint\" : \"%s\",\n", tabs, buffer );
        xrn_bin_to_base64( signature_asy.proof, buffer );
        fprintf( xlog.not_fp, "%s\"proof\" : \"%s\",\n", tabs, buffer );

    }

    if ( filetype == c_ring_signature ) {

        ret = xrn_load_ring_signature( &ring_signature, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1970, XERR_GENERAL_MSG );
            return ( ret );
        }

        fprintf( xlog.not_fp, "%s\"ring_size\" : %u,\n", tabs, ring_signature.ring_size );
        xrn_bin_to_base64( ring_signature.hint, buffer );
        fprintf( xlog.not_fp, "%s\"hint\" : \"%s\",\n", tabs, buffer );
        xrn_bin_to_base64( ring_signature.proof, buffer );
        fprintf( xlog.not_fp, "%s\"proof\" : \"%s\",\n", tabs, buffer );
        xrn_bin_to_base64( ring_signature.binomial_keys[0].start, buffer );
        fprintf( xlog.not_fp, "%s\"start\" : \"%s\",\n", tabs, buffer );
        fprintf( xlog.not_fp, "%s\"ends\" : [\n", tabs );
        for ( i = 0; i < ring_signature.ring_size; i++ ) {
            xrn_bin_to_base64( ring_signature.binomial_keys[0].end, buffer );
            if ( i < ring_signature.ring_size - 1 ) {
                fprintf( xlog.not_fp, "%s%s\"%s\",\n", tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s\"%s\" ]\n}\n", tabs, tabs, buffer );
            }

        }

    }

    if ( filetype == c_certificate_sym ) {

        ret = xrn_load_certificate_sym( &certificate_sym, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1971, XERR_GENERAL_MSG );
            return ( ret );
        }

        fprintf( xlog.not_fp, "%s\"subject\" : \"%s\",\n", tabs, certificate_sym.subject );
        fprintf( xlog.not_fp, "%s\"start_timestamp\" : %ld,\n", tabs, certificate_sym.start_timestamp );
        fprintf( xlog.not_fp, "%s\"end_timestamp\" : %ld,\n", tabs, certificate_sym.end_timestamp );

        xrn_bin_to_base64( certificate_sym.signature.hint, buffer );
        fprintf( xlog.not_fp, "%s\"hint\" : \"%s\", \n", tabs, buffer );
        xrn_bin_to_base64( certificate_sym.signature.proof, buffer );
        fprintf( xlog.not_fp, "%s\"proof\" : \"%s\", \n", tabs, buffer );

        fprintf( xlog.not_fp, "%s\"monovalent_key\" : { \n", tabs );

        fprintf( xlog.not_fp, "%s%s\"start_timestamp\" : %ld,\n", tabs, tabs,
                 certificate_sym.monovalent_key.start_timestamp );
        fprintf( xlog.not_fp, "%s%s\"end_timestamp\" : %ld,\n", tabs, tabs,
                 certificate_sym.monovalent_key.end_timestamp );
        fprintf( xlog.not_fp, "%s%s\"points\" : [\n", tabs, tabs );
        for ( i = 0; i < XRN_STATE_KEY_SIZE; i++ ) {
            xrn_bin_to_base64( certificate_sym.monovalent_key.state[i], buffer );
            if ( i < XRN_STATE_KEY_SIZE - 1 ) {
                fprintf( xlog.not_fp, "%s%s%s\"%s\",\n", tabs, tabs, tabs, buffer );
            } else {
                fprintf( xlog.not_fp, "%s%s%s\"%s\" ]\n%s}\n}", tabs, tabs, tabs, buffer, tabs );
            }

        }

    }

    if ( filetype == c_certificate_asy ) {

        ret = xrn_load_certificate_asy( &certificate_asy, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1972, XERR_GENERAL_MSG );
            return ( ret );
        }

        fprintf( xlog.not_fp, "%s\"subject\" : \"%s\",\n", tabs, certificate_asy.subject );
        fprintf( xlog.not_fp, "%s\"start_timestamp\" : %ld,\n", tabs, certificate_asy.start_timestamp );
        fprintf( xlog.not_fp, "%s\"end_timestamp\" : %ld,\n", tabs, certificate_asy.end_timestamp );

        xrn_bin_to_base64( certificate_asy.signature.hint, buffer );
        fprintf( xlog.not_fp, "%s\"hint\" : \"%s\", \n", tabs, buffer );
        xrn_bin_to_base64( certificate_asy.signature.proof, buffer );
        fprintf( xlog.not_fp, "%s\"proof\" : \"%s\", \n", tabs, buffer );

        fprintf( xlog.not_fp, "%s\"binomial_key\" : { \n", tabs );
        xrn_bin_to_base64( certificate_asy.binomial_key.start, buffer );
        fprintf( xlog.not_fp, "%s%s\"start\" : \"%s\",\n", tabs, tabs, buffer );
        xrn_bin_to_base64( certificate_asy.binomial_key.end, buffer );
        fprintf( xlog.not_fp, "%s%s\"end\" : \"%s\"\n%s}\n}\n", tabs, tabs, buffer, tabs );
        fprintf( xlog.not_fp, "end %s\n", buffer );

    }

    if ( filetype == c_monomial_commitment ) {

        ret = xrn_load_monomial_commitment( &monomial_commitment, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1973, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( monomial_commitment.distance, buffer );
        fprintf( xlog.not_fp, "distance %s\n", buffer );

    }

    if ( filetype == c_monomial_response ) {

        ret = xrn_load_monomial_response( &monomial_response, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1974, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( monomial_response.distance, buffer );
        fprintf( xlog.not_fp, "%s\"distance\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_monomial_proof ) {

        ret = xrn_load_monomial_proof( &monomial_proof, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1975, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( monomial_proof.distance, buffer );
        fprintf( xlog.not_fp, "%s\"distance\" : \"%s\"\n}\n", tabs, buffer );

    }

    if ( filetype == c_binomial_commitment ) {

        ret = xrn_load_binomial_commitment( &binomial_commitment, fpi, &settings );
        final_ret = xrn_store_warnings_in_return_value( ret, final_ret );
        if ( final_ret == XERR_GENERAL ) {
            rewind( fpi );
            XPRINT_ERR( 1976, XERR_GENERAL_MSG );
            return ( ret );
        }

        xrn_bin_to_base64( binomial_commitment.start, buffer );
        fprintf( xlog.not_fp, "%s\"start\" : \"%s\",\n", tabs, buffer );
        xrn_bin_to_base64( binomial_commitment.end, buffer );
        fprintf( xlog.not_fp, "%s\"end\" : \"%s\"\n}\n", tabs, buffer );

    }

    rewind( fpi );

    return final_ret;

}

int xrn_dump_library_info(
 )
{
    XPRINT_DEB(  );

    char tabs[5];

    if ( xlog.not_fp == NULL ) {
        XPRINT_ERR( 1980, XERR_NULL_MSG );
        return XERR_NULL;
    }

    strncpy( tabs, "   ", 4 );
    if ( xlog.not_en ) {
        fprintf( xlog.not_fp,
                 "{\n%s\"message_type\" : \"library_info\",\n%s\"magic_number\" : %u,\n%s\"version\" : %u,\n%s\"algorithms_id\" : %u,\n%s\"files_id\" : %u,\n%s\"component_id\" : %u,\n%s\"revision\" : 0x%08x,\n%s\"dirty_build\" : %d,\n%s\"head_counter\" : %d\n}\n",
                 tabs, tabs, XRN_MAGIC_NUMBER, tabs, XRN_LIB_VERSION, tabs, XRN_ALGORITHM_VERSION, tabs,
                 XRN_IO_VERSION, tabs, XRN_COMPONENT_ID, tabs, XRN_GIT_VERSION, tabs, XRN_GIT_DIRTY_FLAG_INT,
                 tabs, GIT_VERSION );
    }

    return XSUCCESS;

}

